在 python 中透過 ctypes 執行 C++ library 的 class
動機
目前大部份的程式都是用 C++ 來實作,不過有時候會有使用 python 比較方便的時候(例如做 API 的整合測試),這時候可能會在 python 實作一些和 C++ unit test 中一樣的邏輯,但直接重寫一次很容易在日後修改時發生行為不一致的狀況,因此讓 python 能夠直接使用 C++ 的 library 就是比較好的選擇解法選擇
除非本來的 project 就有使用到 boost,否則要將 Boost.Python compile 起來是需要花一些工夫的,這邊會比較建議使用 ctypes library,但是 ctypes 只能夠支援 C 的 interface,這篇文章會教你如何將 C++ 的 class 透過 wrapper 的方法轉到 python 上,這方法是幾個月前從 stackoverflow 上看到的,我覺得比較容易讓 python 和 C++ 上對該 class 的使用體驗一致,分享給大家Example
完整的範例程式碼都有放在 github 上程式解說
每個檔案的說明如下:
- library.h library.cpp: 實作 class
- main.cpp: 使用 library.cpp 提供的 class 做 demo
- library-python.cpp: 提供介面給 ctypes
- library.py: 透過 ctype 提供 python 版本的 class
- ctypes-demo.py: 如同 main.cpp,使用 library.py 提供的 class
TestClass* TestClass_new()
{
return new TestClass();
}
int TestClass_member(TestClass* ptr)
{
return ptr->member();
}
接著在 python 端,就可以透過 ctypes 再把這些 function 包成 python 的 class,我這邊是使用 python3 做測試,一樣截取其中片段import ctypes;
lib = ctypes.CDLL('./liblibrary-python.so');
class TestClass(object):
def __init__(self):
self.obj = lib.TestClass_new()
def member(self):
return lib.TestClass_member(self.obj)
這樣一來,不論我們是在 cpp 或是 python 都可以用幾乎一樣的方式來使用該 class- CPP
TestClass obj;
obj.IncreaseMember();
obj.MultiplyMember(3);
std::cout << "obj.member: " << obj.member() << std::endl;
- Python
obj = TestClass()
obj.IncreaseMember()
obj.MultiplyMember(3)
print('obj.member: ' + str(obj.member()))
不過這個方法要在 cpp 和 python 都寫一份幾乎一樣的介面,如果可以用程式來產生 library-python.cpp 和 library.py 的話會更有效率
作者已經移除這則留言。
回覆刪除