gpt4 book ai didi

go - 如何从cgo获取c变量?

转载 作者:行者123 更新时间:2023-12-01 21:14:31 25 4
gpt4 key购买 nike

package main

/*
#include <malloc.h>
#include <windows.h>
HDC *hdcArr

BOOL CALLBACK EnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
for (int i = 0; i < (_msize(hdcArr) / sizeof(HDC)); i++) {
if (hdcArr[i] == NULL) {
hdcArr[i] = hdcMonitor;
break;
}
}
return TRUE;
}
void Init() {
int count = GetSystemMetrics(SM_CMONITORS);
hdcArr = (HDC*)malloc(sizeof(HDC) * count);
memset(hdcArr, 0, sizeof(HDC) * count);
}
HDC* GetHDC() {
return *hdcArr;
}
*/
import "C"
import (
"fmt"
"reflect"
"unsafe"
".../w32"
)
func main() {
var hdc w32.HDC
hdc = w32.GetDC(0)
C.Init()
w32.EnumDisplayMonitors(hdc, nil, reflect.ValueOf(C.EnumProc).Pointer(), 0)
t := (*[]w32.HDC)(unsafe.Pointer(&C.hdcArr))
cx := w32.GetDeviceCaps((*t)[0], w32.HORZRES)
fmt.Println(cx)
}

我如上所述编写了源代码。

我想要的是将cgo的HDC阵列导入w32.HDC阵列,以了解每个监视器的宽度和高度值。
但是,如果导入 t: = (* [] w32.HDC) unsafe.Pointer (& C.hdcArr))并调用 cx: = w32.GetDeviceCaps ((* t) [0], w32.HORZRES),则仅返回0。

如何使用cgo查找多台显示器的宽度和高度?

最佳答案

package main

/*
#cgo LDFLAGS: -lgdi32
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <windows.h>
HDC *hdcArr;
int count;

BOOL CALLBACK EnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
int i;
for (i = 0; i < (_msize(hdcArr) / sizeof(HDC)); i++) {
if (hdcArr[i] == NULL) {
hdcArr[i] = CreateCompatibleDC(hdcMonitor);
break;
}
}
return TRUE;
}
void Init() {
count = GetSystemMetrics(SM_CMONITORS);
hdcArr = (HDC*)malloc(sizeof(HDC) * count);
memset(hdcArr, 0, sizeof(HDC) * count);
}
*/
import "C"

import (
"fmt"
"reflect"
"unsafe"

"github.com/JamesHovious/w32"
)

func main() {
C.Init()
hdc := w32.GetDC(0)
w32.EnumDisplayMonitors(hdc, nil, reflect.ValueOf(C.EnumProc).Pointer(), 0)
w32.ReleaseDC(0, hdc)
t := (*[256]w32.HDC)(unsafe.Pointer(C.hdcArr))[:C.count:C.count]
for _, dc := range t {
cx := w32.GetDeviceCaps(dc, w32.HORZRES)
fmt.Println(cx)
w32.DeleteDC(dc)
}
C.free(unsafe.Pointer(C.hdcArr))
}

对您来说,理解C-Array的指针只是一个内存地址,而没有任何有关大小的信息(因此,为什么t数组为空)是非常重要的。这就是为什么必须先将其转换为大数组 (*[256]w32.HDC),然后将其切成合适大小的 [:C.count:C.count]的原因

这就是为什么我将 count设置为全局变量。

您遇到的另一个问题是,传递给 EnumProc的hdc句柄仅在回调内部有效。为了使它们在回调范围之外永久且可用,您必须调用 CreateCompatibleDC(hdcMonitor);
要将此功能与cgo一起使用,您将必须通过 #cgo LDFLAGS: -lgdi32包含lib gdi32

使用完这些DC后,您必须使用 w32.DeleteDC(dc)再次释放它们

同样不要忘记使用 C.free(unsafe.Pointer(C.hdcArr))释放您的malloced数组

我的建议:每当您使用WinApi时,请仔细阅读msdn文档。这需要一些时间,但可以省去很多麻烦

您也可以在没有cgo的golang中完全做到这一点:

package main

import (
"fmt"
"syscall"

"github.com/JamesHovious/w32"
)

func EnumProc(hMonitor w32.HMONITOR, hdcMonitor w32.HDC, lprcMonitor *w32.RECT, dwData w32.LPARAM) uintptr {
fmt.Println(w32.GetDeviceCaps(hdcMonitor, w32.HORZRES))
return w32.TRUE
}

func main() {
hdc := w32.GetDC(0)
w32.EnumDisplayMonitors(hdc, nil, syscall.NewCallback(EnumProc), 0)
w32.ReleaseDC(0, hdc)
}

甚至更平滑:

func EnumProc(hMonitor w32.HMONITOR, hdcMonitor w32.HDC, lprcMonitor *w32.RECT, dwData w32.LPARAM) uintptr {
horzres := lprcMonitor.Right - lprcMonitor.Left
fmt.Println(horzres)
return w32.TRUE
}

func main() {
w32.EnumDisplayMonitors(nil, nil, syscall.NewCallback(EnumProc), 0)
}

关于go - 如何从cgo获取c变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60260248/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com