3

I build a .so C++ library using g++ and -fPIC (using eclipse).

Still using eclipse, I linked this library and used it in another C++ project without any problem.

But, When I build a Cython project with that same lib to generate a python extension, using :

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("cyelp", 
              sources=["cyelp.pyx", \
                       "adapter/ATestClass.cpp", \
                       "adapter/ALabSimulatorTime.cpp", \
                       ],
              libraries=["elp"],
              language="c++",
              )
    ]
)

"libelp.so" being the mentioned library, the build is fine too : I get my cyelp.so library.

The problem occurs when I get a specific class from the library at runtime from python side script :

Here is my cython class (that inherits from a ALabSimulationTime:LabSimulationTime class implementing the method FireEvent() - method which is declared as "pure virtual" in LabSimulationTime) :

cimport cpython.ref as cpy_ref

cdef extern from "adapter/ALabSimulatorTime.h" namespace "elps" :
    cdef cppclass ALabSimulatorTime:
        ALabSimulatorTime(cpy_ref.PyObject *obj)
        # Virtual overridable
        void ResetTime()
        double TimeStep()
        void FireEvent()
        void StepSimulation()
        int EndSimulation()
        void RunSimulation()
        # Others
        void UpdateEventsRate(double rate)
        void SetEndTime(double end_time)
        void SetOutputTimeStep(double out_time_step)
        double GetTime()
        int GetNbFiredEvents()
        void SetTime(double time)


cdef class PyLabSimulatorTime:
    cdef ALabSimulatorTime* thisptr

    def __cinit__(self):
       self.thisptr = new ALabSimulatorTime(<cpy_ref.PyObject*>self)

    def __dealloc__(self):
       if self.thisptr:
           del self.thisptr

    cpdef ResetTime(self):
        self.thisptr.ResetTime()

    cpdef double TimeStep(self):
        return self.thisptr.TimeStep()

And here, my python loading attempt :

from cyelp import PyLabSimulatorTime;

Finally, here's the error message :

Traceback (most recent call last):
  File "src/Spacial/BdmLsim2.py", line 1, in <module>
    from cyelp import PyLabSimulatorTime;
ImportError: setup/cyelp.so: undefined symbol: _ZN4elps16LabSimulatorTime9FireEventEv

The fact is that it doesn't happen if I redefine the "FireEvent()" method in ALabSimulatorTime class from the header file :

virtual void FireEvent() {};

But does happen if I redefine the method from the ".cpp" file :

void ALabSimulatorTime::FireEvent()
{
    //...
}

Note : Everything works well if I turn FireEvent to "non-pure" from the base class "LabSimulatorTime".

I could, of course, try to be more specific, but may be some of you already has an idea about what is going on.

Thanks a lot

Gauthier Boaglio
  • 10,054
  • 5
  • 48
  • 85
  • I am not good at linux or python bindings, so just as a comment: Is this a dynamic lib or static? Are both using the exact same compiler? CPP does not have a standard for names - so different compilers name things differently. As a rule of thumb you can only use CPP dynamic linkage between the exact same compiler. Otherwise you have to use C. You might just get lucky in the non pure case. – starmole Oct 04 '12 at 05:11
  • I use g++ in both cases to generate dynamic (-shared) libraries. May be some options differ between the one I compile using my own settings and the options chosen by cython. I could try to get exactly the same compiler options between the 2 things, but I'm not sure it would change anything. And the fact that it behaves differently when redefining from the .h and from .cpp, still seems very strange to me... – Gauthier Boaglio Oct 04 '12 at 05:37
  • Oh, maybe the linker is just stripping out an unused symbol for you. If you have it in the header (that presumably gets included by python) it is just built there. How do you tell g++ what to export when building the lib? Maybe you did that for your base class but not for your derived one? – starmole Oct 04 '12 at 05:47
  • I tries to mimic the compiler options used by cython for 'cyelp.so' in my base shared library building options 'libelp.so' : it doesn't change anything. The only difference I see is : the base class is compiled using g++ as the derived one is compiled using gcc. Do you think it matters ? – Gauthier Boaglio Oct 04 '12 at 11:44
  • I forced cython using g++, now I get : Here are the options for 'libelp.so' : g++ -O2 -g3 -Wall -c -fmessage-length=0 -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -MMD -MP Here for 'libelp.so' (the one containing the base class) : g++ -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes – Gauthier Boaglio Oct 04 '12 at 12:00

0 Answers0