我使用 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 转换为“非纯”,一切正常。
当然,我可以尝试更具体一些,但可能你们中的一些人已经对正在发生的事情有所了解。
非常感谢