用 Golang 和 C 编写的 Python 模块

在 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:


package main


import "fmt"



// #cgo pkg-config: python3

// #define Py_LIMITED_API

// #include <Python.h>

// int PyArg_ParseTuple_S(PyObject *,char *);

import "C"


//export startVM

func startVM(self, args *C.PyObject) {  

    var a *C.char

    if C.PyArg_ParseTuple_S(args, a) == 0 {

        //return nil

    }

    fmt.Println(a)

    //return C.PyBytes_FromString(&a)

}


func main() {}  

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


慕田峪9158850
浏览 191回答 1
1回答

哈士奇WWW

零输出这个功能:int PyArg_ParseTuple_S(PyObject * args, char* a) {&nbsp; &nbsp; return PyArg_ParseTuple(args, "s", &a);}将只设置本地的副本a,并不会使其返回到调用函数,因为按值传递的字符串指针(复制),所以PyArg_ParseTuple只设置副本。var a *C.charC.PyArg_ParseTuple_S(args, a)// Here `a` is not set, so it keeps its default value: nil.您可以通过将指针传递给字符串而不是字符串本身来解决此问题:// Cint PyArg_ParseTuple_S(PyObject * args, char** a) {&nbsp; &nbsp; return PyArg_ParseTuple(args, "s", a);}// Govar a *C.charif C.PyArg_ParseTuple_S(args, &a) == 0 {&nbsp; &nbsp; //return nil}正确印刷fmt.Println(a)将打印 持有的地址a,而不是它指向的字符串。Go 有自己的字符串类型,不适用于 C 字符串。如果要正确打印文本,则必须使用C.GoString以下命令对其进行转换:// C string to Go stringfunc C.GoString(*C.char) string(来自https://golang.org/cmd/cgo/)例如:str := C.GoString(a)fmt.Println(str)分段故障。我不熟悉 python 模块开发,但我可以假设,错误发生了,因为 python 方法应该返回一个有效的PyObject*或NULL. 但是你的代码没有做这些。的返回值startVM没有设置,也不是默认为nil,python接受这个非nil的指针作为一个有效的对象并解引用它,这会导致分段错误。指定返回类型startVM可能会有所帮助://export startVMfunc startVM(self, args *C.PyObject) *C.PyObject {&nbsp;&nbsp;&nbsp; &nbsp; // ...some code...&nbsp; &nbsp; return nil}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go