Golang调用c api的一些坑
- 可以通过查看github.com/kbinani/win里面的master branch 里面有相关的代码。里面的重点代码如下:
winnetapi = doLoadLibrary(“wininet.dll”)
// Functions
internetQueryOptionA = doGetProcAddress(winnetapi, “InternetQueryOptionA”)
internetSetOptionA = doGetProcAddress(winnetapi, “InternetSetOptionA”)
doLoadLibrary使用syscall.LoadLibrary
func doLoadLibrary(name string) uintptr {
lib, _ := syscall.LoadLibrary(name)
return uintptr(lib)
}
func doGetProcAddress(lib uintptr, name string) uintptr {
addr, _ := syscall.GetProcAddress(syscall.Handle(lib), name)
return uintptr(addr)
}
func InternetSetOptionA(hInternet unsafe.Pointer,
dwOption DWORD,
lpBuffer unsafe.Pointer,
dwBufferLength *uint32) bool {
ret1 := syscall6(internetSetOptionA, 4,
uintptr(hInternet),
uintptr(dwOption),
uintptr(lpBuffer),
uintptr(unsafe.Pointer(dwBufferLength)),
0,
0)
return ret1 != 0
}
- 我根据kbinani的自动生成的go. 自己定了winnet.go. 有兴趣可以到github.com/JMVoid/win查看代码。
- syscall3, syscall6是有最多3个或者6个参数。其中nargs是实际有多少个参数. 如上面syscall6就是实际有4个参数。最多可转入6个参数,多的参数用传入
- unsafe.Pointer就是一个无确定类型指针。而uintptr是将一个指针转成一个uint. 如果你要对一个指针进行运算。例如在
(*byte)(unsafe.Pointer(uintptr(p) + uintptr(i)))
如果要进行指针相加运算就需要uintptr之间进行运算。一开始就想着直接+1. 这样是不行的 - 在golang string中的结尾是没有\0的。(因此我也不知道是怎么golang怎么知道结束的)。在InternetQueryOption中返回的option.pzVaule是一个char*。一个指向\0结尾的字符串指针。因此需要这个函数
func LPSTR2Array(p unsafe.Pointer) ([]byte, uint32) {
ar := make([]byte, 0)
for i:=0; i < PROXY_MAX_LEN; i++ {
}bp := (*byte)(unsafe.Pointer(uintptr(p) + uintptr(i))) if uint32(*bp) != uint32(0) { ar = append(ar, *bp) } else { return ar, uint32(i) }
return nil, 0
}
将它转成slice