创建了一个由许多源文件和头文件组成的C库,我现在需要用Python层包装它,所以我可以“导入”它。
我已经实现了从Python调用的静态方法,我需要指定模块应该向解释器公开哪些方法。
但是,the documentation似乎只处理了在指定可调用内容时使用单个源文件的非常简单的情况,因为唯一的非静态方法必须是init,它会注册方法
据我所知,如果在C语言中将方法声明为静态,则无法调用其他源文件中的方法(如果我错了,请纠正我)因此,每个python只能有一个C文件模块,因为你只允许一个非静态的方法。
这是真的吗?如果你想从Python访问代码,你必须严格构建代码吗?
修改
所以,我最终的工作方式是使用Cython。不仅需要大约一个小时来重写c / python接口(之前由于所有引用计数规则而花了大约一天时间),但它还为您处理所有构建问题,并且有明确的文档描述了哪些方法将从python中获得。
特别是,我使用的文档章节是the build instructions,how to call C libraries,the language basics和how to cast types, particularly pointers。
对于那些希望将现有的复杂结构化C代码(即多于一个文件)包装成python库的人,我强烈推荐Cython。
答案 0 :(得分:3)
实际上,模块初始化函数并不是模块中唯一的非静态符号。更多的是最佳实践,可防止污染平面命名空间C用于运行时符号。另一种常见的方法是在所有导出的符号上放置特定于库的前缀。您可以这样做,尽管通常认为静态方法更清晰,更健壮。
答案 1 :(得分:2)
使用头文件使编译器可以访问外部函数。这不是与Python相关的问题,它是C中常见的语言方面。
<强> my_prototypes.h 强>:
// declare the prototype. everybody who includes `my_prototypes.h` now knows that it exists.
PyObject *func_from_other_module(PyObject *self, PyObject *args);
<强> anotherunit.c 强>:
PyObject *func_from_other_module(PyObject *self, PyObject *args) {
// actual implementation
}
<强> mainunit.c 强>:
#include "my_prototypes.h"
static PyMethodDef SpamMethods[] = {
{"func_from_other_module", func_from_other_module, METH_VARARGS,
"Blabla"},
...
{NULL, NULL, 0, NULL} /* Sentinel */
}
你是对的,如果一个函数被声明为static
,它只能从它所包含的文件中使用。你不需要这个 - 只需将static
保留(基本上) ,你甚至不需要标题:将函数声明放在mainunit.c
的顶部也可以。)
答案 2 :(得分:0)
所以,我最终的工作方式是使用Cython。不仅需要大约一个小时来重写c / python接口(之前由于所有引用计数规则而花了大约一天时间),但它还为您处理所有构建问题,并且有明确的文档描述了哪些方法将从python中获得。
特别是,我使用的文档章节是the build instructions,how to call C libraries,the language basics和how to cast types, particularly pointers。
对于那些希望将现有的复杂结构化C代码(即多于一个文件)包装成python库的人,我强烈推荐Cython。