具有多个函数的Py_InitModule - 从int到PyCFunction的无效转换

时间:2015-06-21 03:07:53

标签: c++ python-2.7 boost boost-python python-c-api

我正在转换到删除代码中的boost-python依赖项,并且我已经进入了最后一步"这个过渡(我删除了所有其他的boost依赖项,当我注释掉下面的boost代码时,我得到ImportError: dynamic module does not define init function (initMy_module)。

以下是代码

#include <boost/python.hpp>
namespace bpn = boost::python::numeric;
using namespace boost::python;
BOOST_PYTHON_MODULE(My_module)
{
  using namespace bpn;
  import_array();
  array::set_module_and_type("numpy", "ndarray");

  register_exception_translator<int>(&translator);

  def("run_My_module", run_My_module, "run my moduule");
  def("run_My_module_another_way", run_My_module_another_way, "run my module another way");
}

根据我对python / C API的理解,我认为以下代码应该表面上链接我的C和Python代码。

static PyMethodDef myModule_methods[] = {
    {"run_My_module", run_My_module, METH_VARARGS},
    {"run_My_module_another_way", run_My_module_another_way, METH_VARARGS},
    {NULL, NULL}
    };

void initmyModule(void)
{
    // Init module.
    (void) Py_InitModule("myModule", myModule_methods);

}

但是,这会产生以下错误:

myModule_python_binding.cpp:126:5: error: invalid conversion from 'int (*)(char*, char*, char*, PyObject*) {aka int (*)(char*, char*, char*, _object*)}' to 'PyCFunction {aka _object* (*)(_object*, _object*)}' [-fpermissive]
     };
     ^
myModule_python_binding.cpp:126:5: error: invalid conversion from 'int (*)(char*, ompi_communicator_t*&, char*, char*, PyObject*) {aka int (*)(char*, ompi_communicator_t*&, char*, char*, _object*)}' to 'PyCFunction {aka _object* (*)(_object*, _object*)}' [-fpermissive]

这两种功能都是这种形式。它们都返回整数,表明它们的成功程度。

int run_myModule(char *infile, char *outfile, char *errfile, pyObject *exc)
{...};

int run_myModule_another_way(char *infile, int &_exvar, char *outfile, char *errfile, pyObject *exc)
{...};

为什么我的&#34;表面&#34;连接失败?

1 个答案:

答案 0 :(得分:1)

您收到编译时错误,因为您在myModule_methods[]中使用的函数指针的类型/签名错误。要直接从Python调用的函数需要具有以下签名:

PyObject *foo(PyObject *self, PyObject *args)

因此,如果您想从Python调用run_my_Modulerun_my_Module_another_way函数,则需要在函数和Python之间创建必要的“粘合剂”,方法是将它们包装在具有上述签名的函数中。例如:

static PyObject *run_My_module_wrapper(PyObject *self, PyObject *args)
{
    // Parse arguments from Python out of the args parameter using
    // PyArg_ParseTuple. i.e. somthing like:
    const char *infile, *outfile, *errfile;
    PyObject *exc;

    if (!PyArg_ParseTuple(args, "sssO", &infile, &outfile, &errfile, &exc)) {
        return NULL; // Invalid arguments
    }

    //
    // Now you can call your function with the arguments from the Python call.
    //
    int r = run_My_module(infile, outfile, errfile, exc);

    if (r == SUCCESSFUL_VALUE) {
        Py_RETURN_NONE;
    }
    else {
        return NULL;
    }
}

// Similar setup for run_My_module_another_way.

static PyMethodDef myModule_methods[] = {
    {"run_My_module", run_My_module_wrapper, METH_VARARGS},
    {"run_My_module_another_way", run_My_module_another_way_wrapper, METH_VARARGS},
    {NULL, NULL}
};

void initmyModule(void)
{
    // Init module.
    (void) Py_InitModule("myModule", myModule_methods);

}

有关解析从Python传入的参数的更多信息,请参阅Parsing Arguments。加上Extending and Embedding the Python Interpreter获取您需要的所有常规信息。