大家都知道python的優點是開發效率高,使用方便,c++則是執行效率高,這兩者可以相輔相成,不管是在python專案中嵌入c++**,或是在c++專案中用python實現外圍功能,都可能遇到python呼叫c++模組的需求,下面列舉出集中c++**匯出成python介面的幾種基本方法,一起來學習學習吧。
python直譯器就是用c實現,因此只要我們的c++的資料結構能讓python認識,理論上就是可以被直接呼叫的。我們實現test1.cpp如下
#include int add(int x, int y)
int del(int x, int y)
return py_buildvalue("i", add(x, y));
}
return py_buildvalue("i", del(x, y));
} static pymethoddef test_methods =
};
extern "c"
void inittest1()
編譯命令如下
g++ -fpic -shared test1.cpp -i/usr/include/python2.7 -o test1.so
-fpic:生成位置無關目標**,適用於動態連線;
-l path:表示在path目錄中搜尋庫檔案,如-l.表示在當前目錄;
-i path:表示在path目錄中搜尋標頭檔案;
-o file:制定輸出檔案為file;
-shared:生成乙個共享庫檔案;
執行python直譯器,測試如下
>>> import test1
>>> test1.add(1,2)
3
這裡要注意一下幾點
如果生成的動態庫名字為test1,則原始檔裡必須有inittest1這個函式,且py_initmodule的第乙個引數必須是「test1」,否則python匯入模組會失敗
如果是cpp原始檔,inittest1函式必須用extern "c"修飾,如果是c原始檔,則不需要。原因是python直譯器在導入庫時會尋找init***這樣的函式,而c和c++對函式符號的編碼方式不同,c++在對函式符號進行編碼時會考慮函式長度和引數型別,具體可以通過nm test1.so
檢視函式符號,c++filt工具可通過符號反解出函式原型
我們使用和上面同樣的例子,實現test2.cpp如下
#include #include using namespace boost::python;
int add(const int x, const int y)
int del(const int x, const int y)
boost_python_module(test2)
其中boost_python_module的引數為要匯出的模組名字,編譯命令如下
g++ test2.cpp -fpic -shared -o test2.so -i/usr/include/python2.7 -i/usr/local/include -l/usr/local/lib -lboost_python
注意:編譯時需要指定boost標頭檔案和庫的路徑,我這裡分別是/usr/local/include和/usr/local/lib
或者通過setup.py匯出模組
#!/usr/bin/env python
from distutils.core import setup
from distutils.extension import extension
setup(name="packagename",
ext_modules=[
extension("test2", ["test2.cpp"],
libraries = ["boost_python"])
])
extension的第乙個引數為模組名,第二個引數為檔名
執行如下命令
python setup.py build
這時會生成build目錄,找到裡面的test2.so,並進入同一級目錄,驗證如下
>>> import test2
>>> test2.add(1,2)
3>>> test2.del(1,2)
-1
test3.cpp實現如下
#include using namespace boost::python;
class test
int del(const int x, const int y)
}; boost_python_module(test3)
注意:boost_python_module裡的.def使用方法有點類似python的語法,等同於
class_("test").def("add", &test::add);
class_("test").def("del", &test::del);
編譯命令如下
g++ test3.cpp -fpic -shared -o test3.so -i/usr/include/python2.7 -i/usr/local/include/boost -l/usr/local/lib -lboost_python
測試如下
>>> import test3
>>> test = test3.test()
>>> test.add(1,2)
3>>> test.del(1,2)
-1
test4.cpp實現如下
#include using namespace boost::python;
class test
}; int del(const int x, const int y, const int z = 100)
boost_python_member_function_overloads(add_member_overloads, add, 2, 3)
boost_python_function_overloads(del_overloads, del, 2, 3)
boost_python_module(test4)
這裡add和del函式均採用了預設引數,del為普通函式,add為類成員函式,這裡分別呼叫了不同的巨集,巨集的最後兩個引數分別代表函式的最少引數個數和最多引數個數
編譯命令如下
g++ test4.cpp -fpic -shared -o test4.so -i/usr/include/python2.7 -i/usr/local/include/boost -l/usr/local/lib -lboost_python
測試如下
>>> import test4
>>> test = test4.test()
>>> print test.add(1,2)
103>>> print test.add(1,2,z=3)
6>>> print test4.del(1,2)
-1>>> print test4.del(1,2,z=3)
-1
既然是匯出為python介面,呼叫者難免會使用python特有的資料結構,比如tuple,list,dict,由於原生態方法太麻煩,這裡只記錄boost的使用方法,假設要實現如下的python函式功能
def square(list_a)
即對傳入的list每個元素計算平方,返回list型別的結果,**如下
#include boost::python::list square(boost::python::list& data)
return ret;
}
boost_python_module(test5)
編譯命令如下
g++ test5.cpp -fpic -shared -o test5.so -i/usr/include/python2.7 -i/usr/local/include/boost -l/usr/local/lib -lboost_python
測試如下
>>> import test5
>>> test5.square([1,2,3])
[1, 4, 9]
boost實現了boost::python::tuple
,boost::python::list
,boost::python::dict
這幾個資料型別,使用方法基本和python保持一致,具體方法可以檢視boost標頭檔案裡的boost/python/tuple.hpp及其它對應檔案
另外比較常用的乙個函式是boost::python::make_tuple()
,使用方法如下
boost::python::tuple(int a, int b, int c)
Python 呼叫shell cmd的幾種方式
1.使用os.system 去呼叫,但是只能返回執行狀態,不能獲取shell cmd執行結果 usr bin python coding utf 8 import os status os.system ps aux grep xcode grep v grep print status2.使用os...
Python呼叫C 程式的幾種方法
大家都知道python的優點是開發效率高,使用方便,c 則是執行效率高,這兩者可以相輔相成,不管是在python專案中嵌入c 或是在c 專案中用python實現外圍功能,都可能遇到python呼叫c 模組的需求,下面列舉出集中c 匯出成python介面的幾種基本方法,一起來學習學習吧。python直...
Python呼叫C程式
目錄 python呼叫c程式的意義 呼叫示例 編寫c程式 編譯c程式 呼叫 我們知道,python具有編寫開發快 程式可讀性良好 支援物件導向的特點。種類繁多的python原生庫和第三方框架使python承擔越來越多的任務。但是python自身的缺陷也確實是python開發者要面對的問題 受制於動態...