英文:
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")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论