英文:
golang cgo can't export variables by build mode c-shared
问题
我正在尝试在cgo中开发一个sudo的插件。
https://www.sudo.ws/man/1.8.15/sudo_plugin.man.html
将结构体导出到policy_plugin的全局作用域中。
一个策略插件必须在全局作用域中声明和填充一个
policy_plugin
结构体。
你有关于这是什么意思的解释吗?
export_test.go
package main
/*
#include "sudo_plugin.h"
#include <stddef.h>
*/
import "C"
func main() {
}
// 不起作用
//export policy
var policy = &C.struct_policy_plugin{
C.SUDO_POLICY_PLUGIN,
C.SUDO_API_VERSION,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
}
英文:
I am trying to develop in the cgo a plug-in of sudo.
https://www.sudo.ws/man/1.8.15/sudo_plugin.man.html
export the struct to the global scope of policy_plugin.
> A policy plugin must declare and populate a policy_plugin
struct in the global scope.
Do you have an explanation of what that means?
export_test.go
package main
/*
#include "sudo_plugin.h"
#include <stddef.h>
*/
import "C"
func main() {
}
// don't worked
//export policy
var policy = &C.struct_policy_plugin{
C.SUDO_POLICY_PLUGIN,
C.SUDO_API_VERSION,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
}
答案1
得分: 1
似乎c-shared
构建模式只导出函数入口,而不导出变量。
虽然设计文档没有明确说明这一点,但也没有明确讨论变量。
cmd/cgo
手册也没有明确提到变量,但似乎暗示特殊的//export ...
注释只适用于函数。
你可以尝试在C端声明外部变量,在定义和导出必要的Go函数之后,像这样:
"callbacks.go":
package main
import "C"
//export real_fn
func real_fn(x C.int) C.int {
return 42
}
"main.go":
package main
/*
typedef struct {
int x;
int (*fn) (int x);
} foo;
extern int real_fn(int);
foo xyzzy = {
0,
real_fn,
};
*/
import "C"
func main() {
}
现在运行go build -buildmode=c-shared
后,你可以探索生成的库,并查看xyzzy
符号是否可用:
cshared% nm -g cshared | grep -E 'xyzzy|real_fn'
0000000000061330 T _cgoexp_4f8dd74b8333_real_fn
00000000000b42c0 T real_fn
00000000003274d0 D xyzzy
注意:如果你要使用回调函数,你需要将它们放在单独的文件中(或多个文件中)- 这似乎是cgo
的一个怪癖。
英文:
It appears buildmode c-shared
only exports function entries, not variables.
While the design doc does not state this explicitly, it does not talk about variables explicitly either.
The cmd/cgo
manual also does not mention variables explicitly but seems to imply that the special //export ...
comments apply to functions only.
What you could supposedly do about this is declare your external variable on the C side—after defining and expoting the necessary Go functions, like this:
"callbacks.go":
package main
import "C"
//export real_fn
func real_fn(x C.int) C.int {
return 42
}
"main.go":
package main
/*
typedef struct {
int x;
int (*fn) (int x);
} foo;
extern int real_fn(int);
foo xyzzy = {
0,
real_fn,
};
*/
import "C"
func main() {
}
Now after running go build -buildmode=c-shared
you can explore the generated library and see the xyzzy
symbol available there:
cshared% nm -g cshared | grep -E 'xyzzy|real_fn'
0000000000061330 T _cgoexp_4f8dd74b8333_real_fn
00000000000b42c0 T real_fn
00000000003274d0 D xyzzy
A note: if you're about using callbacks you have to put them into a separate file (or files)—this appears to be a quirk of cgo
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论