c api called by golang

Golang调用c api的一些坑

  1. 可以通过查看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
}

  1. 我根据kbinani的自动生成的go. 自己定了winnet.go. 有兴趣可以到github.com/JMVoid/win查看代码。
  2. syscall3, syscall6是有最多3个或者6个参数。其中nargs是实际有多少个参数. 如上面syscall6就是实际有4个参数。最多可转入6个参数,多的参数用传入
  3. unsafe.Pointer就是一个无确定类型指针。而uintptr是将一个指针转成一个uint. 如果你要对一个指针进行运算。例如在
    (*byte)(unsafe.Pointer(uintptr(p) + uintptr(i)))
    如果要进行指针相加运算就需要uintptr之间进行运算。一开始就想着直接+1. 这样是不行的
  4. 在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