Reputation: 457
My problem is pretty simple, I have a shared library compiled with CMake and I want to write a python wrapper for one cpp class it contains and a standalone function.
Let's say the class is this with the standalone function
// cppClass.cpp
void standalone()
{
printf("I am not alone\n");
}
int cppClass::not_static_method(int value)
{
printf("I am not static\n");
return value;
}
cppClass* cppClass::static_method()
{
cppClass* c = new cppClass();
if (!c) { return NULL; }
return c;
}
// cppClass.h
#ifndef __CPPCLASS_H__
#define __CPPCLASS_H__
void standalone();
class cppClass
{
public:
int not_static_method(int value);
static cppClass* static_method();
};
#endif
So I declare it in my .pxd
file and write a little wrapper class in my .pyx
file:
# .pxd
cdef extern:
cdef cppclass cppClass:
int not_static_method(int value)
@staticmethod
cppClass* static_method()
cdef void standalone()
# .pyx
cdef class PyClass:
cdef cppClass* c_clazz
def __cinit__(self):
self.c_clazz = cppClass.static_method()
def NotStatic(self, value):
standalone()
return self.c_clazz.not_static_method(value)
Problem is, once compiled, I can initialize a PyClass
object but calling the method NotStatic
of the latter object raises an undefined symbol: standalone
and when I comment the call to this function, it raises a segmentation fault
which I think is due to the initialization of the pointer c_clazz
inside the PyClass
object.
I understood that I cannot specify where the definitions are since it is an extern library, and I already specified its name in the setup.py
file as well as its path as extra_link_args
.
What am I doing (possibly extremely) wrong?
Edit: shared library is compiled with g++ -shared -fPIC -c cppClass.cpp -o libcppClass.so
Edit 2: added .h
file
Edit 3: I did not mention why I want to use a shared library, its because the non static method uses some definition in CUDA files compiled into the shared library as well.
Edit 4: my setup file
# setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {"build_ext": build_ext},
ext_modules = [
Extension("cy_wrapper",
sources=["cy_wrapper.pyx"],
libraries=["mycustomlib"],
language="c++",
extra_compile_args=["-O3", "-Wall", "-std=c++11"],
extra_link_args=["-L/absolute/path/to/libmycustomlib.so/directory/"]
)
]
)
Upvotes: 3
Views: 392
Reputation: 6214
Inspecting the code generated by Cython (cy_wrapper.cpp
) shows that
function standalone
is declared as
__PYX_EXTERN_C DL_IMPORT(void) standalone(void);
i.e.
extern "C" void standalone(void);
which is not as defined in cppClass.h
(C++ name mangling issue).
Also cppClass
is somewhat different in the generated file
struct cppClass;
struct cppClass {
virtual int not_static_method(int);
static cppClass *static_method(void);
virtual ~cppClass() { }
};
i.e. not as defined in cppClass.h
. The definitions should match
or there can be trouble like segmentation faults.
I would recommend including the header file in .pxd
file i.e.
cdef extern from "cppClass.h"
Upvotes: 2