【问题标题】:How can I get a c variable from cgo?如何从 cgo 获取 c 变量?
【发布时间】:2020-06-01 06:07:53
【问题描述】:
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 (&amp; C.hdcArr)) 并调用cx: = w32.GetDeviceCaps ((* t) [0], w32.HORZRES),则仅返回0。

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

【问题讨论】:

    标签: go cgo


    【解决方案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) {
        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 数组的指针只是一个内存地址,没有任何有关大小的信息(因此为什么 t 数组为空)。这就是为什么你必须先把它转换成一个大数组(*[256]w32.HDC),然后再把它切成合适的大小[:C.count:C.count]

    这就是我将count 设为全局变量的原因。

    您遇到的另一个问题是传递给 EnumProc 的 hdc 句柄仅在回调中有效。要使它们在回调范围之外永久可用,您必须调用CreateCompatibleDC(hdcMonitor);
    要在 cgo 中使用此功能,您必须通过 #cgo LDFLAGS: -lgdi32 包含 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)
    }
    

    【讨论】:

      猜你喜欢
      • 2014-08-16
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2012-07-13
      • 1970-01-01
      相关资源
      最近更新 更多