Python呼叫C/C++的方法——3(Boost.Python)
阿新 • • 發佈:2019-02-08
之前關於Python呼叫C/C++介紹了:
1.ctypes方式載入並呼叫C/C++ 動態連結庫的方式;
2.使用C/C++編寫Python擴充套件模組的方式。
今天的筆記記錄的是使用Boost.Python的方式。
Boost.Python介紹:
Boost.Python是一個開源C++庫,它提供了一個簡明的IDL式的介面用於繫結C++類和函式到Python。 得益於C++編譯期的內部處理(譯註:原文是introspection)和最近開發的超程式設計(metaprogramming)技術,成就了Boost.Python不需引入一種新的語法而只用純C++的實現。Boost.Python豐富的特性集合以及它的高階介面使得工程師像混合系統(譯註:hybrid system)那樣做打包的事情成為可能,並且程式設計師讓在應用C++高效的編譯期多型性以及Python非常方便的執行期多型性的時候獲得易用性和一致性;
Boost庫是非常強大的庫, 其中的python庫可以用來封裝c++被python呼叫, 功能比較強大, 不但可以封裝函式還能封裝類, 類成員。
前提
使用boost python庫需要先進行安裝,可能有些版本的作業系統內是有整合的。(例如我使用的Ubuntu16.04)
安裝: sudo apt install libboost-python-dev
簡單的例子
hello.cpp
#include <boost/python.hpp> char const* greet() { return "hello, world"; } int add(int x,int y) { return x+y; } BOOST_PYTHON_MODULE(hello) // 引數hello為模組的名字,沒有引號 { using namespace boost::python; def("greet", greet); // "greet"是python調的方法名,greet是C++的方法 def("add",add); }
編譯:
g++ -c -fPIC -o hello.o hello.cpp -I /usr/include/python2.7/ g++ -shared -Wl,-soname,hello.so -o hello.so hello.o -L/usr/lib/x86_64-linux-gnu -lpython2.7 -lboost_python 或: g++ -shared -o hello.so -fPIC hello.cpp -I/usr/include/python2.7/ -lpython2.7 -lboost_python 注意:原始碼hello.cpp的位置一定要在宣告標頭檔案和連結庫的左面(g++自右向左解析)。以下是我趟過的坑: /* g++ -fPIC -o hello.so -shared -I/usr/include/python2.7/ -L/usr/lib/x86_64-linux-gnu -lboost_python hello.cpp 編譯正常通過,且生成hello.so但是ldd發現沒有連結libboost_python這個庫的任何資訊,import 報錯: ''' ImportError: ./hello.so: undefined symbol: _ZNK5boost6python7objects21py_function_impl_base9max_arityEv ''' 此問題既由於g++語句順序不當引起,由於gcc/g++語句都由右向左解析,所以如果把原始碼放在連結庫的右面則有可能連結失敗。 另: 如果boost_python庫的路徑不在ld預設的庫中,可以通過-L新增,例如我的libboost_python.so位置在/usr/lib/x86_64-linux-gnu/下:可以通過:-L/usr/lib/x86_64-linux-gnu指定,或新增到/etc/ld.so.conf.d/中並執行ldconfig */
## python 提供了setup、Extension方法實現編譯和模組建立。
#!/usr/bin/env python
from distutils.core import setup
from distutils.extension import Extension
setup(name="hello.test.python",
ext_modules=[
Extension("hello", ["hello.cpp"], ## hello是模組名,hello.cpp是原始碼檔案
libraries = ["boost_python"]) ## 連結的庫
])
#!/usr/bin/env python
# -*- coding: utf-8 -*-
## 自定義的C++編寫的模組
import hello
if __name__ == "__main__":
## 簡單的兩個測試
print hello.greet()
print hello.add(1,2)
'''
hello, world
3
'''