用Golang和C编写的Python模块

2024-04-19 20:06:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我遵循这个tutorial

要用C编写此代码:

#define Py_LIMITED_API
#include <Python.h>

PyObject * startVM(PyObject *, PyObject *);

int PyArg_ParseTuple_S(PyObject * args, char* a) {  
    return PyArg_ParseTuple(args, "s", &a);
}

static PyMethodDef FooMethods[] = {  
    {"startVM", startVM, METH_VARARGS, "Starts."},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef foomodule = {  
   PyModuleDef_HEAD_INIT, "foo", NULL, -1, FooMethods
};

PyMODINIT_FUNC PyInit_foo(void) {
    return PyModule_Create(&foomodule);
}

GO中的代码:

^{pr2}$

我可以在go中编译代码,但是当我用以下命令调用python模块时:python3 -c 'import foo; foo.startVM("hello")',它将输出nil并导致分段错误。。。 有人知道怎么修吗? 提前谢谢。在


Tags: 代码returnfooargsstaticnulltutorialpyobject
1条回答
网友
1楼 · 发布于 2024-04-19 20:06:15

零输出

此功能:

int PyArg_ParseTuple_S(PyObject * args, char* a) {
    return PyArg_ParseTuple(args, "s", &a);
}

将只设置a本地副本,不会将其返回到调用函数中,因为您通过值(通过复制)传递字符串指针,因此PyArg_ParseTuple只设置副本。在

^{pr2}$

可以通过将指针传递到字符串而不是字符串本身来解决此问题:

// C
int PyArg_ParseTuple_S(PyObject * args, char** a) {
    return PyArg_ParseTuple(args, "s", a);
}

// Go
var a *C.char
if C.PyArg_ParseTuple_S(args, &a) == 0 {
    //return nil
}

正确打印

fmt.Println(a)将打印a持有的地址,而不是它所指向的字符串。Go有自己的字符串类型,不能与C字符串一起使用。在

如果要正确打印文本,则必须使用C.GoString进行转换:

// C string to Go string
func C.GoString(*C.char) string

(来自https://golang.org/cmd/cgo/

例如:

str := C.GoString(a)
fmt.Println(str)

分段错误。

我不熟悉python模块开发,但我可以假设,错误发生了,因为python方法应该返回一个有效的PyObject*或{}。但你的代码不能做到这些。startVM的返回值没有设置,也没有默认为nil,python接受这个非nil指针作为有效对象并取消对它的引用,这会导致分段错误。在

指定startVM的返回类型可能有助于:

//export startVM
func startVM(self, args *C.PyObject) *C.PyObject {  
    // ...some code...
    return nil
}

相关问题 更多 >