簡體   English   中英

在Windows上將結構與Golang syscall一起使用?

[英]Use structs with Golang syscall on Windows?

EnumPrinters Win32函數采用_Out_ LPBYTE pPrinterEnum參數,該指針指向已分配的緩沖區。 在C中,它的工作方式如下:

DWORD cbNeeded, nPrinters;
EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, NULL, 0, &cbNeeded, &nPrinters);

BYTE *pPrnInfo = malloc(cbNeeded);
EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, pPrnInfo, cbNeeded, &cbNeeded, &nPrinters);

PRINTER_INFO_5 *pPrinterInfo = (PRINTER_INFO_5 *) pPrnInfo;
for (int i=0; i < nPrinters; i++) {
  printf("pPrinterName: %s\n", pPrinterInfo[i].pPrinterName);
}

使用syscall而不是cgo在Go中如何完成相同的工作? 到目前為止,已經編譯了很多,但是我不知道如何將結果字節片轉換為結構數組(不使用cgo)。

type PrinterInfo5 struct {
    pPrinterName             *uint16
    pPortName                *uint16
    attributes               uint32
    deviceNotSelectedTimeout uint32
    transmissionRetryTimeout uint32
}

...

dll := syscall.MustLoadDLL("winspool.drv")
f := dll.MustFindProc("EnumPrintersW")

var cbNeeded, nPrinters uint32
fmt.Println(cbNeeded, nPrinters)
f.Call(PRINTER_ENUM_LOCAL, 0, 5, 0, 0, uintptr(unsafe.Pointer(&cbNeeded)), uintptr(unsafe.Pointer(&nPrinters)))
fmt.Println(cbNeeded, nPrinters)

var pPrnInfo []byte = make([]byte, cbNeeded)
f.Call(PRINTER_ENUM_LOCAL, 0, 5, uintptr(unsafe.Pointer(&pPrnInfo)), uintptr(cbNeeded), uintptr(unsafe.Pointer(&cbNeeded)), uintptr(unsafe.Pointer(&nPrinters)))

我已經嘗試過了,它可以成功打印一次迭代,然后失敗並出現fatal error: heapBitsBulkBarrier: unaligned arguments

hdr := reflect.SliceHeader{
  Data: uintptr(unsafe.Pointer(&pPrnInfo)),
  Len:  int(nPrinters),
  Cap:  int(nPrinters),
}
s := *(*[]PrinterInfo5)(unsafe.Pointer(&hdr))
for _, t := range s {
  fmt.Println(t)
}
uintptr(unsafe.Pointer(&pPrnInfo))

上面代碼中的兩個地方都是錯誤的; 它為您提供了指向切片標頭的指針,而不是實際的后備數組的指針。 您想要這個:

uintptr(unsafe.Pointer(&pPrnInfo[0]))

(由於支持數組是連續的,所以指向支持數組第一個元素的指針與指向支持數組本身的指針相同。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM