英文:
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
我在这里做错了什么?
英文:
I was trying to learn and understand cgo.
I am writing a program in Go where I connect to AD and parse the output. I tested the code in C, which is working fine as expected. The relevant part in C is
char *ldap_host = "x.x.x.x";
int ldap_port = 389;
ldap = ldap_init(ldap_host, ldap_port))
Now I am trying to get the same working in go as
//#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)
}
But I am getting the following error
could not determine kind of name for C.ldap_init
What am I doing wrong here?
答案1
得分: 4
我会开始先让Go和cgo的基础工作正常运行,然后再添加类似ldap这样的库的个别特性。一些很好的起点,尤其是官方的cgo文档页面。
从头开始:
这里不需要CFLAGS,但是你需要LDFLAGS来链接器,并且需要liblber才能运行。
#cgo LDFLAGS: -lldap -llber
你不能将Go字符串的指针传递给C的*char,它们是不同的类型。实际上,Go中的字符串根本不可寻址,所以如果构建过程到达这一步,这将是一个编译错误。使用C.CString,如果需要创建C字符串,则使用C.free。你还需要包含stdlib.h以使用C.free。
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")
}
英文:
I would start by getting the basics of Go and cgo working before adding the individual peculiarities of a library like ldap. Some good starting points, especially the official cgo doc page.
Starting from the top:
You don't need the CFLAGS here, but you will need LDFLAGS for the linker, and liblber for this to run.
#cgo LDFLAGS: -lldap -llber
You can't pass a pointer to a Go string as a C *char, they are different types. Strings in Go actually aren't addressable at all, so this would be a compile error if the build process got that far. Use C.CString, and C.free if you need to create C strings. You will also need to include stdlib.h for C.free.
url := C.CString(os.Args[1])
defer C.free(unsafe.Pointer(url))
Go's int size varies by architecture, and is not C's int type. ldap_port in your example is converted to the default type of int, where you would have needed C.int.
Finally, the original error in your question has nothing to do with Go or cgo. The ldap_init function is deprecated, and does not exist without setting LDAP_DEPRECATED. You should use the ldap_initialize function. Here is a minimal example that compiles:
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")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论