尝试将 Python 代码移植到 cython 时,我收到以下链接器错误消息:
cls ~/workspace/Prototypes/PLPcython $ python3 setup.py build_ext --inplace
running build_ext
cythoning src/graph.pyx to src/graph.c
cythoning src/community.pyx to src/community.c
building 'PLPcython' extension
creating build
creating build/temp.macosx-10.8-x86_64-3.3
creating build/temp.macosx-10.8-x86_64-3.3/src
cc -Wno-unused-result -fno-common -dynamic -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -I/usr/local/include -I/usr/local/opt/sqlite/include -I/usr/local/Cellar/python3/3.3.0/Frameworks/Python.framework/Versions/3.3/include/python3.3m -c src/graph.c -o build/temp.macosx-10.8-x86_64-3.3/src/graph.o
cc -Wno-unused-result -fno-common -dynamic -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -I/usr/local/include -I/usr/local/opt/sqlite/include -I/usr/local/Cellar/python3/3.3.0/Frameworks/Python.framework/Versions/3.3/include/python3.3m -c src/community.c -o build/temp.macosx-10.8-x86_64-3.3/src/community.o
src/community.c:1414:19: warning: expression result unused [-Wunused-value]
PyObject_INIT(o, t);
~~~~~~~~~~~~~~^~~~~
/usr/local/Cellar/python3/3.3.0/Frameworks/Python.framework/Versions/3.3/include/python3.3m/objimpl.h:163:69: note: expanded from macro 'PyObject_INIT'
( Py_TYPE(op) = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )
^
1 warning generated.
cc -bundle -undefined dynamic_lookup -L/usr/local/lib -L/usr/local/opt/sqlite/lib build/temp.macosx-10.8-x86_64-3.3/src/graph.o build/temp.macosx-10.8-x86_64-3.3/src/community.o -o /Users/cls/workspace/Prototypes/PLPcython/PLPcython.so
duplicate symbol _PyInit_PLPcython in:
build/temp.macosx-10.8-x86_64-3.3/src/graph.o
build/temp.macosx-10.8-x86_64-3.3/src/community.o
duplicate symbol ___pyx_module_is_main_PLPcython in:
build/temp.macosx-10.8-x86_64-3.3/src/graph.o
build/temp.macosx-10.8-x86_64-3.3/src/community.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
error: command 'cc' failed with exit status 1
显然会产生重复的符号。什么是_PyInit_*
和___pyx_module_is_main_
?
这些是我尝试 cythonize 的两个源文件:graph.pyx
class Graph:
def __init__(self, n=0):
self.n = n
self.m = 0
self.z = n # max node id
self.adja = [[] for i in range(self.z)]
self.deg = [0 for i in range(self.z)]
def maxNodeId(self):
return self.z
def numberOfNodes(self):
return self.n
def numberOfEdges(self):
return self.m
def addEdge(self, u, v):
if (u == v):
self.adja[u].append(v)
self.deg[u] += 1
else:
self.adja[u].append(v)
self.adja[v].append(u)
self.deg[u] += 1
self.deg[v] += 1
self.m += 1
def hasEdge(self, u, v):
for w in self.adja[u]:
if w == v:
return True
return False
def degree(self, u):
return self.deg[u]
def forNodes(self, handle):
# assumtion: all nodes exist
for u in range(self.z):
handle(u)
def forEdges(self, handle):
for u in range(self.z):
for v in self.adja[u]:
if v <= u:
handle(u, v)
def forNeighborsOf(self, u, handle):
for v in self.adja[u]:
handle(v)
和community.pyx
def numberOfCommunities(zeta, G):
labels = set()
for label in zeta:
if label is not None:
labels.add(label)
return len(labels)
def coverage(zeta, G):
intra = 0
inter = 0
m = G.numberOfEdges()
def scan(u, v):
nonlocal intra
nonlocal inter
if zeta[u] == zeta[v]:
intra += 1
else:
inter += 1
G.forEdges(scan)
print("intra-community edges: ", intra)
print("inter-community edges: ",inter)
assert (inter + intra == m)
coverage = intra / m
return coverage