golang cgo无法通过构建模式c-shared导出变量。

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

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 &quot;sudo_plugin.h&quot;
#include &lt;stddef.h&gt;
*/
import &quot;C&quot;

func main() {
}

// don&#39;t worked
//export policy
var policy = &amp;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 &quot;C&quot;

//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 &quot;C&quot;

func main() {
}

现在运行go build -buildmode=c-shared后,你可以探索生成的库,并查看xyzzy符号是否可用:

cshared% nm -g cshared | grep -E &#39;xyzzy|real_fn&#39;
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&mdash;after defining and expoting the necessary Go functions, like this:

"callbacks.go":

package main

import &quot;C&quot;

//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 &quot;C&quot;

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 &#39;xyzzy|real_fn&#39;
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)&mdash;this appears to be a quirk of cgo.

huangapple
  • 本文由 发表于 2016年3月25日 08:27:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/36212246.html
匿名

发表评论

匿名网友

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

确定