使用Python C-API动态注册函数

时间:2014-03-20 16:44:23

标签: python c python-2.7 cpython

我正在寻找一种让Python C函数在其模块中注册其他Python C函数的方法。

通常使用以下函数在共享库中静态声明函数:

Py_InitModule(module_name, functions);

我在cpython中看一下Py_InitModule实现,并尝试:

  • 使用我的第一个函数Py_InitModule
  • 注册一个模块
  • 让第一个函数获取模块字典:
PyModule_GetDict(module) 
  • 从c函数生成新的python函数:
PyCFunction_NewEx(&method, (PyObject*)NULL, n)
  • 将新功能添加到模块字典中:
PyDict_SetItemString(d, method.ml_name, v) != 0

然而,当我尝试调用新函数时,它会出现故障。

我做错了什么? 甚至可以用CPython做这样的事情吗?

更确切地说,这是一个完整的例子:

static int load_extra_methods(void)
{
    PyMethodDef module_methods[] = {
        {
             "my_new_method",
             my_new_method,
             METH_VARARGS,
        },
        /* possibly more functions here */
    };
    const char *name = "module_name";
    PyObject *d = PyModule_GetDir(_G.pymodule);
    PyObject *n;

    if(_Py_PackageContext != NULL) {
        char *p = strrchr(_Py_PackageContext, '.');
        if (p != NULL && strcmp(name, p + 1) == 0) {
            name = _Py_PackageContext;
            _Py_PackageContext = NULL;
        }
    }
    n = PyString_FromString(name);

    for (int i = 0; i < countof(module_methods); i++) {
        PyMethodDef method = module_methods[i];
        PyObject *v = PyCFunction_NewEx(&method, (PyOBject*)NULL, n);

        if (v == NULL) {
            Py_DECREF(n);
        }
        if (PyDict_SetItemString(d, method.ml_name, v) != 0) {
            Py_DECREF(v);
            Py_DECREF(n);
            return -1;
        }
        Py_DECREF(v);
    }
    return 0;
    Py_DECREF(n);
}

上面的这个函数是由先前使用通常的Py_InitModule3函数公开的另一个函数调用的。 上面的代码大量借用了CPython实现本身(Python / modsupport.c Py_InitModule4)。

修改

我错放了Py_DECREF(n); (现在在示例代码中修复)。 现在我有了:

SystemError: ../Objects/methodobject.c:120: bad argument to internal function

0 个答案:

没有答案