gpt4 book ai didi

go - 如何调用自定义dll文件中的函数

转载 作者:数据小太阳 更新时间:2023-10-29 03:24:45 26 4
gpt4 key购买 nike

现在我得到了这样描述的函数

int ReadCard(char *room,char *gate,char *stime, char *guestname, char *guestid, char *lift, char *track1, char *track2, long *cardno, int *st, int *Breakfast);`

这就是我做的

room := ""
gate := ""
stime := ""
guestname := ""
guestid := ""
lift := ""
track1 := ""
track2 := ""
cardno := int64(0)
st := int64(0)
Breakfast := int64(0)

MAINDLL, _ := syscall.LoadLibrary("xxxxx.dll")
defer syscall.FreeLibrary(MAINDLL)
readCard, _ := syscall.GetProcAddress(MAINDLL, "ReadCard")

r1, r2, errno := syscall.Syscall12(readCard,
11,
uintptr(unsafe.Pointer(&room)),
uintptr(unsafe.Pointer(&gate)),
uintptr(unsafe.Pointer(&stime)),
uintptr(unsafe.Pointer(&guestname)),
uintptr(unsafe.Pointer(&guestid)),
uintptr(unsafe.Pointer(&lift)),
uintptr(unsafe.Pointer(&track1)),
uintptr(unsafe.Pointer(&track2)),
uintptr(cardno),
uintptr(st),
uintptr(Breakfast),
0)

fmt.Println(r1, "\n", r2, "\n", errno)`

当我运行这段代码时,我得到了

r1:0    r2:917452    errno:<nil>

但是当我打印 room 或其他参数时,它的值不会改变,dll 文件中的这个函数会改变我发送的参数,我怎样才能得到这些值?

最佳答案

要检索 C 的NULL 终止字符串,请使用指向预分配 byte slice 的指针而不是字符串。您需要确保 byte slice 有足够的空间来存储字符,否则您的程序可能会因内存访问冲突而崩溃。

对于long *int * 类型,需要变量的地址,例如使用 uintptr(unsafe.Pointer(&cardno)) 而不是 uintptr(cardno)。在您当前的实现中,变量指向的值被转换为指针。所有 uintptr(cardno)uintptr(st)uintptr(Breakfast) 都指向同一个指针(指针在 C) 中为 NULL,因为它们都被初始化为 0。

代码如下:

const maxSize = 100 //Adjust the value to your need

room := make([]byte, maxSize)
gate := make([]byte, maxSize)
stime := make([]byte, maxSize)
guestname := make([]byte, maxSize)
guestid := make([]byte, maxSize)
lift := make([]byte, maxSize)
track1 := make([]byte, maxSize)
track2 := make([]byte, maxSize)

//The following variable type is correct for 64-bit DLL.
//For 32-bit DLL, instead of int64, use int32.
cardno := int64(0)
st := int64(0)
Breakfast := int64(0)

MAINDLL, _ := syscall.LoadLibrary("xxxxx.dll")
defer syscall.FreeLibrary(MAINDLL)
readCard, _ := syscall.GetProcAddress(MAINDLL, "ReadCard")

r1, r2, errno := syscall.Syscall12(readCard,
11,
uintptr(unsafe.Pointer(&room[0])),
uintptr(unsafe.Pointer(&gate[0])),
uintptr(unsafe.Pointer(&stime[0])),
uintptr(unsafe.Pointer(&guestname[0])),
uintptr(unsafe.Pointer(&guestid[0])),
uintptr(unsafe.Pointer(&lift[0])),
uintptr(unsafe.Pointer(&track1[0])),
uintptr(unsafe.Pointer(&track2[0])),
uintptr(unsafe.Pointer(&cardno)),
uintptr(unsafe.Pointer(&st)),
uintptr(unsafe.Pointer(&Breakfast)),
0)

fmt.Println(r1, "\n", r2, "\n", errno)

请注意,在上面的示例中,我们使用的是 &room[0] 而不是 room,因为我们需要传递底层字节数组的地址而不是地址 slice 描述符(参见 https://blog.golang.org/go-slices-usage-and-internals )。

最后,包含 NULL 终止字符串 的字节 slice 必须转换为 gostring,例如使用:

func cstr(buf []byte) string {
str := string(buf)
for i, r := range str {
if r == 0 {
return string(buf[:i])
}
}
return str
}

//usage example
sRoom := cstr(room)
//see the difference
fmt.Printf("`%s` => `%s`\n", string(room), sRoom)

其他实现示例,参见How can I convert a null-terminated string in a byte buffer to a string in Go? .

关于go - 如何调用自定义dll文件中的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45076323/

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