2014-01-07 132 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()