【发布时间】:2014-04-09 19:10:35
【问题描述】:
我有一些 C++ 代码 dbscan.cpp 和 dbscan.h 可以独立运行。现在我正试图将它包装在 Cython 中。我不确定如何正确执行此操作,而且我对编译器和链接器以及库和 makefile 的了解有限。
这里是PyDBSCAN_lib.pyx:
# distutils: language = c++
# distutils: sources = dbscan.cpp
from libcpp.vector cimport vector
from libcpp.string cimport string
from libcpp cimport bool
cdef extern from "dbscan.h":
cdef cppclass DBSCAN:
#DBSCAN(int minPts, int eps) except +
DBSCAN(int minPts) except +
void start()
void findNeighbors(int pid, vector[int]& neighbors)
void readFile(string filename, bool lastColIsTrueCluster)
void buildDistMatrix()
void calcEps()
void calcNumNeighbors()
void initLabels()
void writeFile(string filename)
cdef class PyDBSCAN:
cdef DBSCAN *thisptr
def __cinit__(self, int minPts):
self.thisptr = new DBSCAN(minPts)
def __dealloc__(self):
del self.thisptr
def start(self):
self.thisptr.start()
def findNeighbors(self, int pid, vector[int]& neighbors):
self.thisptr.findNeighbors(pid, neighbors)
def readFile(self, string filename, bool lastColIsTrueCluster):
self.thisptr.readFile(filename, lastColIsTrueCluster)
def buildDistMatrix(self):
self.thisptr.buildDistMatrix()
def calcEps(self):
self.thisptr.calcEps()
def calcNumNeighbors(self):
self.thisptr.calcNumNeighbors()
def initLabels(self):
self.thisptr.initLabels()
def writeFile(self, string filename):
self.thisptr.writeFile(filename)
如您所见,上半部分引用了我的 c++ 代码,而下半部分是一个包装类。
这是setup.py,我理解它有点像makefile:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
#from Cython.Build import cythonize
import os
os.environ['CC'] = '/app/gcc/4.8.2/bin/g++ -std=c++11'
os.environ['CXX'] = '/app/gcc/4.8.2/bin/g++ -std=c++11'
os.environ['CPP'] = '/app/gcc/4.8.2/bin/g++ -std=c++11'
os.environ['CMAKE_CXX_COMPILER'] = '/app/gcc/4.8.2/bin/g++ -std=c++11'
modules = [Extension("PyDBSCAN_lib",
sources=["PyDBSCAN_lib.pyx"],
include_dirs = [".", "/usr/local/elemental/0.81/HybridRelease/include"],
libraries = ["mpi_cxx", "mpi", "m", "elemental"],
library_dirs = ["/usr/local/lib", "/usr/lib", "/usr/local/elemental/0.81/HybridRelease/lib"],
language = "c++")]
setup(ext_modules = modules, cmdclass = {"build_ext" : build_ext})
我正在尝试生成PyDBSCAN_lib.so,以便可以将其导入任何常规 python 脚本中。
我的问题是 dbscan.cpp 使用了 Elemental 库中的某些类型,而我在 setup.py 中找不到正确的配置来指定它。目前它会生成这个:
/usr/bin/ld: /usr/local/elemental/0.81/HybridRelease/lib/libelemental.a(matrix.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/local/elemental/0.81/HybridRelease/lib/libelemental.a: could not read symbols: Bad value
collect2: error: ld returned 1 exit status
编辑:为了记录,这是我用 g++ 编译它的方式
include /usr/local/elemental/0.81/HybridRelease/conf/elemvariables
db: dbscan_main.cpp dbscan.cpp
${CXX} ${ELEM_COMPILE_FLAGS} -fopenmp $^ -o $@ ${ELEM_LINK_FLAGS} ${ELEM_LIBS}
其中 elemvariables 包含各种编译选项,但 -fPIC 不在其中。
如果能提供任何帮助,我将不胜感激。谢谢。
【问题讨论】: