1. 程式人生 > >[Bug]Python3.x AttributeError: libtest.so: undefined symbol: fact

[Bug]Python3.x AttributeError: libtest.so: undefined symbol: fact

ack 後綴 ini print python3 call traceback undefined ron

寫kNN,需要在python中實現kd-tree
思考了一下,在python下寫這種算法類的東西,還是十分別扭
於是希望用ctypes調用一下c++動態加載庫

於是嘗試實現一下

// test.cpp
long long fact(int n){
    return (n<=0):1:(fact(n-1)*n);
}

// gcc -shared -fpic test.cpp  -o libtest.so
// test.py
import ctypes

lib=ctypes.cdll.LoadLibrary("libtest.so")
print(lib.fact(10))

於是報錯

Traceback (most recent call last):                              
  File "<stdin>", line 1, in <module>                    
  File "/usr/lib/python3.6/ctypes/__init__.py", line 361, in __getattr__
    func = self.__getitem__(name)                    
  File "/usr/lib/python3.6/ctypes/__init__.py", line 366, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: libtest.so: undefined symbol: fact 

最後百度發現原因是c++的編譯後,函數名會被改變(為了實現重載)
用extern "C"聲明後,就會使用c的方式進行編譯,編譯後的文件中仍然是定義的函數名

解決方法

  1. 改後綴為.c
  2. 聲明為"C", 以c方式編譯即可
// test,cpp
// g++ -fpiv -shared test.cpp -o libtest.so
extern "C"{
    long long fact(int);
}

long long fact(int n){
    return (n<=0):1:(fact(n-1)*n);
}

[Bug]Python3.x AttributeError: libtest.so: undefined symbol: fact