Go cgo ldap_init 无法确定 C.ldap_init 的名称种类

Go cgo ldap_init could not determine kind of name for C.ldap_init

我正在尝试学习和理解 cgo。 我正在用 Go 编写一个程序,我连接到 AD 并解析输出。我在 C 中测试了代码,它按预期工作正常。 C中的相关部分是

char *ldap_host = "x.x.x.x";
int   ldap_port     = 389;
ldap = ldap_init(ldap_host, ldap_port)) 

现在我正试图在 go 中实现与

相同的工作
//#cgo CFLAGS: -lldap 
//#include <ldap.h>
import "C"
func main() {
    var hostname *string
    hostname = &os.Args[1]
    ldap_port := 389
    ldap := C.ldap_init(*hostname, ldap_port)
}

但我收到以下错误

could not determine kind of name for C.ldap_init

我做错了什么?

我会先了解 Go 和 cgo 的基础知识,然后再添加像 ldap 这样的库的个别特性。一些很好的起点,尤其是官方的 cgo 文档页面。

从顶部开始:

这里不需要 CFLAGS,但是链接器需要 LDFLAGS,运行 需要 liblber

#cgo LDFLAGS: -lldap -llber

您不能将指向 Go 字符串的指针作为 C *char 传递,它们是不同的类型。 Go 中的字符串实际上根本不可寻址,因此如果构建过程进行到这一步,这将是一个编译错误。如果需要创建 C 字符串,请使用 C.CStringC.free。您还需要为 C.free 添加 stdlib.h

    url := C.CString(os.Args[1])
    defer C.free(unsafe.Pointer(url))

Go 的 int 大小因架构而异,不是 C 的 int 类型。 ldap_port 在您的示例中转换为默认类型 int,您需要 C.int.

最后,你问题中的原始错误与Go或cgo无关。 ldap_init 函数已弃用,如果不设置 LDAP_DEPRECATED 则不存在。您应该使用 ldap_initialize 函数。这是一个最小的编译示例:

package main

import (
    "log"
    "unsafe"
)

/*
#include <stdlib.h>
#include <ldap.h>

#cgo LDFLAGS: -lldap -llber
*/
import "C"

func main() {
    url := C.CString("ldap://127.0.0.1:389/")
    defer C.free(unsafe.Pointer(url))

    var ldap *C.LDAP

    rv := C.ldap_initialize(&ldap, url)
    if rv != 0 {
        log.Fatalf("ldap_initialize() error %d", rv)
    }
    log.Println("initialized")
}