3

我使用 g++ 和 -fPIC(使用 eclipse)构建了一个 .so C++ 库。

仍然使用eclipse,我链接了这个库并在另一个C++项目中使用它没有任何问题。

但是,当我使用相同的库构建 Cython 项目以生成 python 扩展时,使用:

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”是提到的库,构建也很好:我得到了我的 cyelp.so 库。

当我在运行时从 python 端脚本从库中获取特定类时,就会出现问题:

这是我的 cython 类(继承自 ALabSimulationTime:LabSimulationTime 类,实现方法 FireEvent() - 在 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()

在这里,我的 python 加载尝试:

from cyelp import PyLabSimulatorTime;

最后,这是错误消息:

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

事实是,如果我从头文件中重新定义 ALabSimulatorTime 类中的“FireEvent()”方法,则不会发生这种情况:

virtual void FireEvent() {};

但是如果我从“.cpp”文件重新定义方法,确实会发生:

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

注意:如果我从基类“LabSimulatorTime”将 FireEvent 转换为“非纯”,一切正常。

当然,我可以尝试更具体一些,但可能你们中的一些人已经对正在发生的事情有所了解。

非常感谢

4

0 回答 0