简体   繁体   中英

Embed python function in C++

I am experimenting with Cython to generate c code from python but there seems to be some issues with name mangling. I first generate convert the code from python to c code and then I compile the code using gcc into a .so . The reason I want to use cython instead of C/python API is because I will be later using this on more complicated classes that I would like to be a library for speed etc later on (I am having a lot of trouble finding people who go from python to C++ since it is usually the other way around). Below is all the code that I have to try to execute the code (but fails). Any input will be appreciated. Thanks!

#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

Here is the error message:

/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 

You're not going to be able to get the interoperation you want that way. If you open and inspect hello.c you won't find "static int say_hello" anywhere in there. Cython is designed for letting Python use C libraries, not letting C libraries use python.

You can look here in the documentation, but unfortunately this support is still for a python interpreter that is "in charge" and what you're looking for is the other way around.

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

There's also the primer on "Embedding Python in Another Application"

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

I don't know what your requirements are, but in some cases you can successfully write data to a file, call a Python program to chew on it, then parse the results from another file. It's a little ugly and slower than keeping things in memory but it's entirely workable in many situations.

I encountered a similar problem. It's not exactly the same problem, but it might be related.

I posted my question here: Propagating exceptions through dlsym cython . The part that is interesting for you is the 'public' keyword:

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

That will create a function like this

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

Edit: I have added a working temp.cpp:

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

#include "hello.h"

using namespace std;

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

Compiling is done with:

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

(interestingly, it will not link in one step, complaining about undefined references.) This will successfully print 'Hello world' upon execution.

Note: The Py_Initialize() and inithello() are necessary, otherwise your code will crash. I haven't been able to get it to work without including "Python.h" and without the initialization parts (ie using only extern "C" { void sayhello(); } as you mention). It fails at linking. The solution can be to use dlsym and dynamically load your function, as I demonstrate in my question. But probably another solution exists, where you try to successfully export this method (in the hello.h header): __PYX_EXTERN_C DL_IMPORT(int) say_hello(void);

If you have CMake I suggest to take a look to my project, where I use CMake to generate and link Cython based files

https://github.com/CarloNicolini/cymake

You probably have to edit some CMakeLists.txt to find the right cython installation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM