4

我正在尝试使用 Cython 从 python 生成 c 代码,但名称修饰似乎存在一些问题。我首先生成将代码从 python 转换为 c 代码,然后使用 gcc 将代码编译为 .so 。我想使用 cython 而不是 C/python API 的原因是因为我稍后将在更复杂的类上使用它,我想稍后成为一个库以提高速度等(我很难找到去的人从 python 到 C++,因为它通常是相反的)。下面是我必须尝试执行代码的所有代码(但失败)。任何输入将不胜感激。谢谢!

#hello.pyx
def say_hello():
    print "Hello World!"

#generate the c code
cython -a hello.pyx

#creates the shared library
gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python2.6 -o libhello.so hello.c

//temp.cpp
#include <iostream>
extern "C" {
void say_hello();
};

using namespace std;

int main(){
    say_hello();
    return 1;
};

#attempt to compile (this is where it fails)
g++ -I/usr/include/python2.6/ -lpython2.6 -L./ -lhello temp.cpp -o temp

这是错误消息:

/tmp/ccpKHOMl.o: In function main: temp.cpp:(.text+0x5): undefined reference to say_hello' /tmp/ccpKHOMl.o: 
In function __static_initialization_and_destruction_0(int, int): 
  temp.cpp:(.text+0x33): undefined reference to std::ios_base::Init::Init()  
  temp.cpp:(.text+0x38): undefined reference to std::ios_base::Init::~Init() 
collect2: ld returned 1 exit status 
4

3 回答 3

3

您将无法以这种方式获得所需的互操作性。如果您打开并检查 hello.c,您将不会在其中的任何地方找到“static int say_hello”。Cython 旨在让 Python 使用 C 库,而不是让 C 库使用 python。

您可以在文档中查看here,但不幸的是,这种支持仍然适用于“负责”的python解释器,而您正在寻找的是相反的方式。

http://docs.python.org/release/2.5.4/ext/callingPython.html

还有关于“在另一个应用程序中嵌入 Python”的入门

http://docs.python.org/2/extending/embedding.html

我不知道您的要求是什么,但在某些情况下,您可以成功地将数据写入文件,调用 Python 程序对其进行处理,然后从另一个文件中解析结果。它比将内容保存在内存中有点难看和慢,但在许多情况下它是完全可行的。

于 2012-12-11T04:37:21.797 回答
1

我遇到了类似的问题。这不是完全相同的问题,但可能是相关的。

我在这里发布了我的问题:Propagating exceptions through dlsym cython。您感兴趣的部分是“public”关键字:

#hello.pyx
cdef public say_hello():
    print "Hello World!"

这将创建一个这样的函数

# (in the generated C file hello.c)
__PYX_EXTERN_C DL_IMPORT(...) say_hello(...);

编辑:我添加了一个工作 temp.cpp:

#include "Python.h"
#include <iostream>

#include "hello.h"

using namespace std;

int main(){
    Py_Initialize();
    inithello();
    say_hello();
    Py_Finalize();
    return 1;
};

编译通过以下方式完成:

g++ -I/usr/include/python2.6/ -lpython2.6 -L./ -lhello temp.cpp -c -o temp.o
g++ temp.o -L. -lhello -lpython2.6 -o temp

(有趣的是,它不会一步链接,抱怨未定义的引用。)这将在执行时成功打印“Hello world”。

注意: Py_Initialize() 和 inithello() 是必需的,否则你的代码会崩溃。如果不包括“Python.h”和没有初始化部分(即只使用你提到的 extern "C" { void sayhello(); }),我就无法让它工作。链接失败。正如我在问题中所展示的,解决方案可以是使用 dlsym 并动态加载您的函数。但可能存在另一种解决方案,您尝试成功导出此方法(在 hello.h 标头中): __PYX_EXTERN_C DL_IMPORT(int) say_hello(void);

于 2013-01-11T14:48:05.297 回答
0

如果您有 CMake,我建议您查看我的项目,在那里我使用 CMake 生成和链接基于 Cython 的文件

https://github.com/CarloNicolini/cymake

您可能需要编辑一些 CMakeLists.txt 才能找到正确的 cython 安装

于 2013-01-11T14:57:31.577 回答