Cython:从C程序调用Python代码

时间:2014-01-07 01:13:59

标签: python c cython

我正在尝试创建一个Cython包装器,因此我可以从C调用Python代码。我遇到导入问题,因为我希望包装器与原始代码分开。

调用导入的函数时,下面的代码以 segfault 结尾。如果代码被编写为python模块并通过import导入,则程序会显示name ... is not defined。当一切都在一个文件中并且没有涉及导入时(实际上由Cython生成的代码在cimporting时失败),问题不会出现。当libcimpy.pyx从其他python脚本导入(编译为.so或live)时,代码也能正常工作

我准备了一个最小的例子。这远非实际代码,但涵盖了原则。

cimpPy.pyx:示例python代码(转换为Cython)

cdef sum(a, b):
    return a + b

cimpPy.pxd

cdef sum(a, b)

libcimpy.pyx(胶水Cython代码)

cimport cimpPy

cdef public int cSum(int a, int b):
    return cimpPy.sum(a, b)

ci.c(c代码,我们想从中调用cimpPy)

#include <stdio.h>
#include <stdlib.h>
#include <Python.h>
#include "libcimp.h"

int main(int argc, char **argv) {
  Py_Initialize();
  initlibcimp();
  int a = 2;
  int b = 3;
  int c = cSum(a, b);
  printf("sum of %d and %d is %d\n", a, b, c);
  Py_Finalize();
  return 0;
}

生成文件

EXECUTABLE = ci

OBJS       = ci.o

CC         = gcc
CFLAGS     = -g -I/usr/include/python2.7 -I$(shell pwd)

LINKER     = g++
LDFLAGS    = -L$(shell pwd) $(shell python-config --ldflags) -lcimp
.PHONY: clean cython

all: cython $(EXECUTABLE)

cython:
    python setup.py build_ext --inplace

.c.o:
    $(CC) $(CFLAGS) -c $<

$(EXECUTABLE) : $(OBJS)
    $(LINKER) -o $(EXECUTABLE) $(OBJS) $(LDFLAGS)

clean:
    rm -rf *.o *.so libcimp.c libcimp.h core build $(EXECUTABLE)

setup.py

from distutils.core import setup, Extension
from Cython.Build import cythonize
from Cython.Distutils import build_ext

extensions = [
    Extension("libcimp", ["libcimp.pyx"])
]

setup(
    name = "CIMP",
    cmdclass = {"build_ext": build_ext},
    ext_modules = cythonize(extensions)
)

我打算实现的是能够将Python代码插入更大的C系统。假设用户将能够自己编写Python。 C代码是一个模拟引擎,可以在环境中的代理上运行。这个想法是代理和环境的行为可以在python中指定,并在必要时传递给引擎进行评估。最好的比喻是map reduce系统,其中Python脚本是映射器。在这个意义上,我想从C调用Python,而不是相反。

将所有内容转换为Cython,同时引人注目的是大型活动。

这是正确的做法吗?为什么导入只能在python解释器下工作而不能在外部嵌入时工作?任何建议和参考文章或文件表示赞赏。

1 个答案:

答案 0 :(得分:2)

在此代码中,initlibcimp()实际上已失败,但您无法立即看到它,因为错误是通过设置python异常来报告的。我不是100%确定这是正确的方法,但我可以通过在调用下面添加以下代码来查看错误:

if (PyErr_Occurred())
{
    PyErr_Print();
    exit(-1);
}

然后,程序将输出:

Traceback (most recent call last):
  File "libcimpy.pyx", line 1, in init libcimpy (libcimpy.c:814)
    cimport cimpPy
ImportError: No module named cimpPy

cimpPy模块尚未定义的原因是,您需要在致电initcimpPy()之前致电initlibcimp