Cgo:找不到使用带有const char*参数的回调函数的方法

huangapple go评论94阅读模式
英文:

Cgo: can't find way to use callbacks with const char* argument

问题

我使用Cgo从Go中使用C库,除了回调函数之外都很好。库有一个回调函数设置器,它接受指向回调函数的指针。回调函数本身是用Go编写的,并使用Cgo语法导出。

问题是:我可以创建和导出带有char *参数的函数,但无法使用const char *

以下是用于说明的代码:

test.go:

package main

/*
typedef void (*cb_func)(const char *, int);
void callback(cb_func);
void myFunc(const char *, int);
*/
import "C"
import (
	"fmt"
	"unsafe"
)

//export myFunc
func myFunc(buf *C.char, ln C.int) {
	fmt.Printf("Got: %s\n", C.GoStringN(buf, ln))
}

func main() {
	C.callback((C.cb_func)(unsafe.Pointer(C.myFunc)))
}

test.c:

typedef void (*cb_func)(const char *, int);

void callback(cb_func cb) {
	cb("test", 4);
}

go build的输出:

In file included from $WORK/test/_obj/_cgo_export.c:2:0:
./test.go:54:13: error: conflicting types for 'myFunc'
./test.go:7:6: note: previous declaration of 'myFunc' was here
 void myFunc(const char *, int);
      ^
/tmp/go-build994908053/test/_obj/_cgo_export.c:9:6: error: conflicting types for 'myFunc'
 void myFunc(char* p0, int p1)
      ^
In file included from $WORK/test/_obj/_cgo_export.c:2:0:
./test.go:7:6: note: previous declaration of 'myFunc' was here
 void myFunc(const char *, int);
      ^

如果没有const限定符,代码将编译并按预期工作。

在C中,可以使用*C.char以外的什么来获取常量字符串?

英文:

I'm use C library from Go using Cgo and all good except callbacks. Library have callback setter, which takes pointer to callback func. Callback func itself written in go and exported using Cgo syntax.
Problem: I can make and export function with char * argument, but can't with const char *.

Code to illustrate:
test.go:

package main

/*
typedef void (*cb_func)(const char *, int);
void callback(cb_func);
void myFunc(const char *, int);
*/
import "C"
import (
        "fmt"
        "unsafe"
)

//export myFunc
func myFunc(buf *C.char, ln C.int) {
        fmt.Printf("Got: %s\n", C.GoStringN(buf, ln))
}

func main() {
        C.callback((C.cb_func)(unsafe.Pointer(C.myFunc)))
}

test.c:

typedef void (*cb_func)(const char *, int);

void callback(cb_func cb) {
        cb("test", 4);
}

Output from go build:

In file included from $WORK/test/_obj/_cgo_export.c:2:0:
./test.go:54:13: error: conflicting types for 'myFunc'
./test.go:7:6: note: previous declaration of 'myFunc' was here
 void myFunc(const char *, int);
      ^
/tmp/go-build994908053/test/_obj/_cgo_export.c:9:6: error: conflicting types for 'myFunc'
 void myFunc(char* p0, int p1)
      ^
In file included from $WORK/test/_obj/_cgo_export.c:2:0:
./test.go:7:6: note: previous declaration of 'myFunc' was here
 void myFunc(const char *, int);
      ^

Without const qualifiers code compiles and works as expected.

What can be used insted of *C.char to get const string in C?

答案1

得分: 7

由于Go语言中没有指针的const修饰符,所以无法在Go代码内部实现这种行为的转换。cgo始终会生成没有const修饰符的头文件。这也是你的代码无法正确构建的原因:cgo仅根据它所知道的信息创建myFuncbuf应该是char*,而不是const char*

处理这个问题的最佳方法是在C端使用一个将该参数转换为const char*的包装器。在你的情况下,只需将myFunc的定义更改为void myFunc(char*, int)即可。将函数传递给cb_func将仍然有效,因为将myFunc强制转换为(*cb_func)(const char*,int)只是添加了类型信息,但不会改变内存布局。

英文:

Since Go does not have const modifiers for pointers there is no way to translate this behaviour from inside Go code. cgo will always generate headers that do not have the const modifier. This is also the reason why your code does not build correctly: cgo creates myFunc only based on what it knows: buf should be char*, not const char*.

The best way to handle this is to use wrapper on the C side that casts that parameter to const char*. In your case it is enough to change the definition of myFunc to void myFunc(char*, int). Passing the function to cb_func will work regardless since casting myFunc to (*cb_func)(const char*,int) only adds type information but does not change the memory layout.

答案2

得分: 7

我遇到了同样的问题。对于仍然需要的解决方案之一是这样做:

typedef const char cchar_t;
void myNewFunction(cchar_t* data);

然后在Go语言中使用它作为 data* C.char_t

英文:

I had the same issue. One solution for the still-needee is to something like:

typedef const char cchar_t
void myNewFunction(cchar_t* data);

then use it in go as data* C.char_t

huangapple
  • 本文由 发表于 2015年10月5日 05:23:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/32938558.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定