2014-01-07 130 views
4

我想制作一个Cython包装器,以便我可以从C调用Python代码。我遇到导入问题,因为我希望包装与原始代码分开。Cython:从C程序调用Python代码

下面的代码在的段落结束时段落当调用导入的函数。如果代码是作为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) 

Cl。 c(我们想从中调用cimpPy的c代码)

#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; 
} 

的Makefile

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代码为更大的空调系统。假设用户将能够自己编写Python。 C代码是一个模拟引擎,可以在环境中的代理上运行。这个想法是,代理和环境的行为可以在python中指定,并在必要时传递给引擎进行评估。最好的比喻是Python脚本是映射器的映射缩减系统。从这个意义上说,我想从C调用Python,而不是相反。

将所有东西都转换成Cython,而引人注目的是大型事业。

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

+0

http://docs.python.org/2/extending/extending。html#calling-python-functions-from-c –

+0

在回答“这是正确的方法吗?”时,试图澄清情况。如果你打算让用户用Python编写代码,并为你的C仿真引擎提供一个Python接口,那么你就是这样做了。上面,你试图从C接口Python代码,而不是反之。就像你说的那样,如果你想“将Python代码插入到更大的C系统”,那么这样做是可行的。但是如果你想为引擎创建一个接口,以便用户可以从python编程,你想从python中调用c,而不是从c中调用python。 – gg349

+0

@flebool我在回复之后意识到,我并没有对我想要达到的目标提供很好的解释。 C代码是一个模拟引擎,可以在环境中的代理上运行。这个想法是,代理和环境的行为应在python中指定,并在必要时传递给引擎进行评估。最好的比喻是Python脚本是映射器的映射缩减系统。从这个意义上说,我想从C调用Python,而不是相反。 – robert3005

回答

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模块尚未定义的原因是您需要在致电initlibcimp之前拨打initcimpPy()