英文:
Calling C function pointer as callback from Go code
问题
我尝试从Go函数中调用一个C函数指针作为回调,但是遇到了一个我不理解的链接器错误。
错误信息如下:
c:/mingw32/bin/../lib/gcc/i686-w64-mingw32/11.2.0/../../../../i686-w64-mingw32/bin/ld.exe: $WORK\b001\_x002.o: in function `bridge_int_int':
./test.go:6: multiple definition of `bridge_int_int'; $WORK\b001\_x001.o:/tmp/test.go:6: first defined here
collect2.exe: error: ld returned 1 exit status
我不明白这个多重定义问题是从哪里来的。
英文:
I try to call a C function pointer as a callback from a Go function but get a linker error I don't understand.
package main
/*
typedef void (*int_int)(int, int);
void bridge_int_int(int a, int b, int_int f){
f(a, b);
}
*/
import "C"
//export IntIntCallback
func IntIntCallback(a, b C.int, cb C.int_int) {
C.bridge_int_int(a, b, cb)
}
func main() {
// Noop, required to make CGO happy: `-buildmode=c-*` requires exactly one
// main package, which in turn needs a `main` function`.
}
The error is:
c:/mingw32/bin/../lib/gcc/i686-w64-mingw32/11.2.0/../../../../i686-w64-mingw32/bin/ld.exe: $WORK\b001\_x002.o: in function `bridge_int_int':
./test.go:6: multiple definition of `bridge_int_int'; $WORK\b001\_x001.o:/tmp/test.go:6: first defined here
collect2.exe: error: ld returned 1 exit status
I don't understand where this multiple definition problem comes from.
答案1
得分: 2
问题已解决。请参阅:https://pkg.go.dev/cmd/cgo#hdr-C_references_to_Go
在文件中使用//export会对前言产生限制:由于它被复制到两个不同的C输出文件中,它不能包含任何定义,只能包含声明。如果一个文件既包含定义又包含声明,那么两个输出文件将产生重复的符号,链接器将失败。为了避免这种情况,定义必须放在其他文件的前言中,或者放在C源文件中。
将以下代码移动到一个单独的.go文件中:
/*
typedef void (*int_int)(int, int);
void bridge_int_int(int a, int b, int_int f){
f(a, b);
}
*/
import "C"
并将其更改为:
/*
typedef void (*int_int)(int, int);
extern bridge_int_int(int a, int b, int_int f);
}
*/
import "C"
...
在原始文件中解决了这个问题。
英文:
Problem solved. See: https://pkg.go.dev/cmd/cgo#hdr-C_references_to_Go
> Using //export in a file places a restriction on the preamble: since it is copied into two different C output files, it must not contain any definitions, only declarations. If a file contains both definitions and declarations, then the two output files will produce duplicate symbols and the linker will fail. To avoid this, definitions must be placed in preambles in other files, or in C source files.
Moving the following code into a separate .go file:
/*
typedef void (*int_int)(int, int);
void bridge_int_int(int a, int b, int_int f){
f(a, b);
}
*/
import "C"
and changing it to
/*
typedef void (*int_int)(int, int);
extern bridge_int_int(int a, int b, int_int f);
}
*/
import "C"
...
in the original file solved the problem
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论