如何从 cgo 获取 ac 变量?

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 查找多个显示器的宽度和高度?


开满天机
浏览 104回答 1
1回答

拉丁的传说

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) {&nbsp; &nbsp; int i;&nbsp; &nbsp; for (i = 0; i < (_msize(hdcArr) / sizeof(HDC)); i++) {&nbsp; &nbsp; &nbsp; &nbsp; if (hdcArr[i] == NULL) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hdcArr[i] = CreateCompatibleDC(hdcMonitor);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return TRUE;}void Init() {&nbsp; &nbsp; count = GetSystemMetrics(SM_CMONITORS);&nbsp; &nbsp; hdcArr = (HDC*)malloc(sizeof(HDC) * count);&nbsp; &nbsp; memset(hdcArr, 0, sizeof(HDC) * count);}*/import "C"import (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "reflect"&nbsp; &nbsp; "unsafe"&nbsp; &nbsp; "github.com/JamesHovious/w32")func main() {&nbsp; &nbsp; C.Init()&nbsp; &nbsp; hdc := w32.GetDC(0)&nbsp; &nbsp; w32.EnumDisplayMonitors(hdc, nil, reflect.ValueOf(C.EnumProc).Pointer(), 0)&nbsp; &nbsp; w32.ReleaseDC(0, hdc)&nbsp; &nbsp; t := (*[256]w32.HDC)(unsafe.Pointer(C.hdcArr))[:C.count:C.count]&nbsp; &nbsp; for _, dc := range t {&nbsp; &nbsp; &nbsp; &nbsp; cx := w32.GetDeviceCaps(dc, w32.HORZRES)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(cx)&nbsp; &nbsp; &nbsp; &nbsp; w32.DeleteDC(dc)&nbsp; &nbsp; }&nbsp; &nbsp; C.free(unsafe.Pointer(C.hdcArr))}对您来说理解这一点非常重要,指向 C 数组的指针只是一个内存地址,没有任何有关大小的信息(因此您的 t 数组为空)。这就是为什么你必须先把它转换成一个大数组(*[256]w32.HDC),然后再把它切成合适的大小[:C.count:C.count]这就是为什么我创建了count一个全局变量。您遇到的另一个问题是传递给的 hdc 句柄EnumProc仅在回调中有效。要使它们在回调范围之外永久可用,您必须调用CreateCompatibleDC(hdcMonitor);.要将此功能与 cgo 一起使用,您必须通过以下方式包含 lib gdi32#cgo LDFLAGS: -lgdi32一旦你用完这些 DC,你必须再次释放它们w32.DeleteDC(dc)也不要忘记释放你的 malloced 数组C.free(unsafe.Pointer(C.hdcArr))我的建议:每当您使用 WinApi 时,请仔细阅读 msdn 文档。这需要一些时间,但可以为您省去很多麻烦您也可以在没有 cgo 的情况下完全在 golang 中执行此操作:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "syscall"&nbsp; &nbsp; "github.com/JamesHovious/w32")func EnumProc(hMonitor w32.HMONITOR, hdcMonitor w32.HDC, lprcMonitor *w32.RECT, dwData w32.LPARAM) uintptr {&nbsp; &nbsp; fmt.Println(w32.GetDeviceCaps(hdcMonitor, w32.HORZRES))&nbsp; &nbsp; return w32.TRUE}func main() {&nbsp; &nbsp; hdc := w32.GetDC(0)&nbsp; &nbsp; w32.EnumDisplayMonitors(hdc, nil, syscall.NewCallback(EnumProc), 0)&nbsp; &nbsp; w32.ReleaseDC(0, hdc)}甚至更平滑:func EnumProc(hMonitor w32.HMONITOR, hdcMonitor w32.HDC, lprcMonitor *w32.RECT, dwData w32.LPARAM) uintptr {&nbsp; &nbsp; horzres := lprcMonitor.Right - lprcMonitor.Left&nbsp; &nbsp; fmt.Println(horzres)&nbsp; &nbsp; return w32.TRUE}func main() {&nbsp; &nbsp; w32.EnumDisplayMonitors(nil, nil, syscall.NewCallback(EnumProc), 0)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go