這篇文章主要介紹了將Python代碼嵌入C++程序進行編寫的實例,盡管通常還是Python代碼中調用C++程序的情況較多...需要的朋友可以參考下
站在用戶的角度思考問題,與客戶深入溝通,找到鉛山網站設計與鉛山網站推廣的解決方案,憑借多年的經驗,讓設計與互聯(lián)網技術結合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網站設計、做網站、企業(yè)官網、英文網站、手機端網站、網站推廣、主機域名、虛擬空間、企業(yè)郵箱。業(yè)務覆蓋鉛山地區(qū)。
把python嵌入的C++里面需要做一些步驟
安裝python程序,這樣才能使用python的頭文件和庫
在我們寫的源文件中增加“Python.h”頭文件,并且鏈入“python**.lib”庫(還沒搞清楚這個庫時靜態(tài)庫還是導出庫,需要搞清楚)
掌握和了解一些python的C語言api,以便在我們的c++程序中使用
常用的一些C API函數(shù)
在了解下面的函數(shù)之前有必要了解一下**PyObject***指針,python里面幾乎所有的對象都是使用這個指針來指示的。
Py_Initialize()Py_Finalize()
在調用任何python的c函數(shù)之前需要調用的函數(shù),“Py_Initialize”是用來初始化python模塊的,推測是加載初始化加載dll的。對應的在使用python模塊之后用“Py_Finalize”來釋放模塊。
PyImport_ImportModule()
用來載入一個python模塊,這個模塊就是一般的python文件。這里需要注意的是,在加載這個模塊的時候會執(zhí)行模塊里面所有可以執(zhí)行的語句。包括import導入語句和在函數(shù)體之外的所有語句
PyObject_GetAttrString()
返回模塊里面的函數(shù)
Py_BuildValue()
建立一個參數(shù)元組,一般都是用這個函數(shù)來建立元組,然后將這個元組作為參數(shù)傳遞給python里面的函數(shù)。
PyEval_CallObject()
調用函數(shù),并把“Py_BuildValue”建立的元組作為參數(shù)傳遞給被調用的函數(shù)
源碼實例
下面的實例是在c++代碼中調用Python的函數(shù),傳遞參數(shù)并且獲取返回值
test.cpp代碼
[cpp]?view plain?copy
#include?iostream
#include?Python.h
using?namespace?std;
int?main(int?argc,?char*?argv[])
{
Py_Initialize();??//初始化
PyObject*?pModule?=?NULL;
PyObject*?pFunc?=?NULL;
PyObject*?pParam?=?NULL;
PyObject*?pResult?=?NULL;
const?char*?pBuffer?=?NULL;
int?iBufferSize?=?0;
pModule?=?PyImport_ImportModule(“test_python");
if?(!pModule)
{
cout??"get?module?failed!"??endl;
exit?(0);
}
pFunc?=?PyObject_GetAttrString(pModule,?"main");
if?(!pFunc)
{
cout??"get?func?failed!"??endl;
cout??int(pFunc)??endl;
exit?(0);
}
pParam?=?Py_BuildValue("(s)",?"HEHEHE");
pResult?=?PyEval_CallObject(pFunc,pParam);
if(pResult)
{
if(PyArg_Parse(pResult,?"(si)",?pBuffer,?iBufferSize))
{
cout??pBuffer??endl;
cout??iBufferSize??endl;
}
}
Py_DECREF(pParam);
Py_DECREF(pFunc);
Py_Finalize();
//cout??"hello"??endl;
return?0;
}
test_python.py代碼
[py]?view plain?copy
def?main(szString):
return?("hello",?5)
python的用途:
Python的優(yōu)勢有必要作為第一步去了解,Python作為面向對象的腳本語言,優(yōu)勢就是數(shù)據(jù)處理和挖掘,這也注定了它和AI、互聯(lián)網技術的緊密聯(lián)系。
網絡爬蟲。顧名思義,從互聯(lián)網上爬取信息的腳本,主要由urllib、requests等庫編寫,實用性很強,小編就曾寫過爬取5w數(shù)據(jù)量的爬蟲。在大數(shù)據(jù)風靡的時代,爬蟲絕對是新秀。
人工智能。AI使Python一戰(zhàn)成名,AI的實現(xiàn)可以通過tensorflow庫。神經網絡的核心在于激活函數(shù)、損失函數(shù)和數(shù)據(jù),數(shù)據(jù)可以通過爬蟲獲得。訓練時大量的數(shù)據(jù)運算又是Python的show time。
擴展資料:
Python開發(fā)人員盡量避開不成熟或者不重要的優(yōu)化。一些針對非重要部位的加快運行速度的補丁通常不會被合并到Python內。在某些對運行速度要求很高的情況,Python設計師傾向于使用JIT技術,或者用使用C/C++語言改寫這部分程序??捎玫腏IT技術是PyPy。
Python是完全面向對象的語言。函數(shù)、模塊、數(shù)字、字符串都是對象。并且完全支持繼承、重載、派生、多繼承,有益于增強源代碼的復用性。
Python支持重載運算符和動態(tài)類型。相對于Lisp這種傳統(tǒng)的函數(shù)式編程語言,Python對函數(shù)式設計只提供了有限的支持。有兩個標準庫(functools, itertools)提供了Haskell和Standard ML中久經考驗的函數(shù)式程序設計工具。
參考資料來源:百度百科-Python
主要原因,內置函數(shù)用C寫的。在Python語言內無論如何造不出內置函數(shù)的輪子。這也是通常C跟C++語言用戶更喜歡造基礎算法的輪了的原因。因為C/C++用戶真有條件寫出匹敵標準庫的算法,但很多高級語言不行,不是程序員技術差,是客觀條件就根本做不到。
你比如說Java語言沒人造字符串的輪子,C++光一個字符串類就有無數(shù)多的實現(xiàn)。是因為C+用戶更喜歡寫字符串類嗎?顯然不是,一方面是因為Java語言內沒法造出匹敵Java內置標準庫算法的輪子,而C++真的可以,另外一個比較慘的原因是C++標準庫的字符串功能太弱了,大多數(shù)高級語言的字符串類功能都比C+標準庫字符串類功能更強。
寫C++的時候一大錯覺就是我覺著我能比標準庫還快,同樣的道理放在Python里面也同樣適用,不管是Python各種常用package或內建函數(shù),基本上都針對實用場景作了優(yōu)化,自己手寫的算法一般是比不上內建算法效率的,這也是為什么用Python時不鼓勵自己造輪子的原因。
回到這個問題,Python內建的sort本質上為C實現(xiàn)的函數(shù),本身執(zhí)行效率就會比Python快很多,并且會根據(jù)不同的數(shù)據(jù)規(guī)模采用不同的排序算法,故效率一般都會優(yōu)于自己在Python里面手寫的排序更何況題主寫的是基于遞歸的quicksort9,額外時間開銷大。
因為python內置的sort是用c語言寫的,如果你用c語言或者c++寫的話肯定是可以做到一樣快的至于為什么python計算效率比c語言能慢100倍這個具體的原理我不清楚,不過鑒于知乎上已經有很多大佬解釋過這個問題,我就不在這里班門弄斧了
還有底下扯timsort的,快排序是所有比較排序算法里平均性能最優(yōu)的一族算法,像C++和rust里的unstable_sort都是用的快排序??赡茉谝恍┣闆r下,比如數(shù)組幾乎有序時,timsort會比快排序快。但是你隨便給一個數(shù)組,比如像題主那樣隨機一個一百萬大小的數(shù)然后排序,timsort是絕對不可能比快排序快的。絕對不可能??斓倪@100倍和timsort屁關系都沒有。
我是C/C++程序員,我可以很負責的告訴你,在用天下現(xiàn)有所有高級語言進行排序的問題上,C要是認了第二,則沒人敢認第一。所以,我猜,Python以及好多其他高級語言,都會時不時直接上C語言寫的靜態(tài)庫和動態(tài)庫。我自己也造了不少輪子,有部分是因為剛剛起步,對系統(tǒng)API和函數(shù)庫不熟悉,找不到適合的,所以自己造輪子,后來發(fā)現(xiàn)了有更好的,我把我寫的拋棄了。但這里也不排除有一部分是因為我個人覺得還有優(yōu)化的空間,所以自己用C語言重新造了一個輪子,這樣效率比現(xiàn)成的更優(yōu)。
所以說,要論高級語言的鼻祖,還真非C莫屬,從執(zhí)行效率上講,別說python,JAVA,C#,VB,甚至C的親兒子C++,在同一個程序員手中,都沒法與C抗衡,所以說,這些語言都是排著隊等著被C吊打的,也正因為如此,所以,像python這類高級語言,有自帶函數(shù)可用的,最好別想著自己重新造輪子,因為你不可能造出比自帶函數(shù)更快的輪子。
內置庫函數(shù)都是用C實現(xiàn)的,肯定要比手寫的Python程序執(zhí)行效率更高,此外內置排序Timsort相比本科課程上學的時間復雜度為Onlogn的排序算法做了很多常數(shù)優(yōu)化,所以對于普通人而言,不要希望純手寫出來的東西效率能和標準庫相當了。另外,題主寫的排序是過不了LeetCode上的裸排序題目的,隨機選取pivot對于快速排序是最基本的優(yōu)化雖然題主排的是隨機數(shù),現(xiàn)在這么選肯定不是效率低的主要原因。
所以說了,py幾乎得把自己的循環(huán)體拆了,這就是py和c/c++的性能差距,必須盡量用內置函數(shù)和numpy來處理數(shù)據(jù),一旦手寫循環(huán)體。,那你就得知道這可能得慢百倍,像用opency的py版時你不小心寫個雙循環(huán)來處理數(shù)據(jù),那酸爽,而cppc#搞opencv就能隨意用指針來寫循環(huán),這也是為啥他們其實不需要numpy這種組件,自身就有足夠的性能和靈活度來處理這個。
Cpp內置的排序是快排和堆排的結合,最壞時間復雜度為nlogn,而快排最壞是n2。至于python內部的排序,我認為是一個道理,不會簡簡單單是一個快排,舉個簡單例子,當你數(shù)據(jù)已經是有序的時候,再傳入快排肯定就不合適。那你設置排序函數(shù)的時候,是不是預先將他打亂,再進行快排會更好呢。當然具體不會這么簡單,只是我認為官方給的接口都是很精妙的,很值得學習。
一方面Python中sort函數(shù)是用C語言寫的,C++內部的sort是由快排,直接插入和堆排序混合的,當數(shù)據(jù)量比較大的時候先用的快排,當數(shù)據(jù)量小的時候用直接插入,因為當數(shù)據(jù)量變小時,快排中的每個部分基本有序,接近直接插入的最好情況的時間復雜度O(n),就比快排要好一點了。
另外一方面這個的底層實現(xiàn)就是歸并排序。,只是使用了Python無法編寫的底層實現(xiàn),從而避免了Python本身附加的大量開銷,速度比我們自己寫的歸并排序要快很多,所以說我們一般排序都盡量使用sorted和sort。
將event.py目錄加入到system path中
1
2
3
import sys
sys.path.append("/Users/songrao/Library/Application Support/Sublime Text 3/Packages/User/")
from event import printme
Python是解釋性語言, 底層就是用c實現(xiàn)的, 所以用python調用C是很容易的, 下面就總結一下各種調用的方法, 給出例子, 所有例子都在ubuntu9.10, python2.6下試過
1. Python 調用 C (base)
想在python中調用c函數(shù), 如這兒的fact
#include Python.h
int fact(int n)
{
if (n = 1)
return 1;
else
return n * fact(n - 1);
}
PyObject* wrap_fact(PyObject* self, PyObject* args)
{
int n, result;
if (! PyArg_ParseTuple(args, "i:fact", n))
return NULL;
result = fact(n);
return Py_BuildValue("i", result);
}
static PyMethodDef exampleMethods[] =
{
{"fact", wrap_fact, METH_VARARGS, "Caculate N!"},
{NULL, NULL}
};
void initexample()
{
PyObject* m;
m = Py_InitModule("example", exampleMethods);
}
把這段代碼存為wrapper.c, 編成so庫,
gcc -fPIC wrapper.c -o example.so -shared -I/usr/include/python2.6 -I/usr/lib/python2.6/config
然后在有此so庫的目錄, 進入python, 可以如下使用
import example
example.fact(4)
2. Python 調用 C++ (base)
在python中調用C++類成員函數(shù), 如下調用TestFact類中的fact函數(shù),
#include Python.h
class TestFact{
public:
TestFact(){};
~TestFact(){};
int fact(int n);
};
int TestFact::fact(int n)
{
if (n = 1)
return 1;
else
return n * (n - 1);
}
int fact(int n)
{
TestFact t;
return t.fact(n);
}
PyObject* wrap_fact(PyObject* self, PyObject* args)
{
int n, result;
if (! PyArg_ParseTuple(args, "i:fact", n))
return NULL;
result = fact(n);
return Py_BuildValue("i", result);
}
static PyMethodDef exampleMethods[] =
{
{"fact", wrap_fact, METH_VARARGS, "Caculate N!"},
{NULL, NULL}
};
extern "C" //不加會導致找不到initexample
void initexample()
{
PyObject* m;
m = Py_InitModule("example", exampleMethods);
}
把這段代碼存為wrapper.cpp, 編成so庫,
g++ -fPIC wrapper.cpp -o example.so -shared -I/usr/include/python2.6 -I/usr/lib/python2.6/config
然后在有此so庫的目錄, 進入python, 可以如下使用
import example
example.fact(4)
3. Python 調用 C++ (Boost.Python)
Boost庫是非常強大的庫, 其中的python庫可以用來封裝c++被python調用, 功能比較強大, 不但可以封裝函數(shù)還能封裝類, 類成員.
首先在ubuntu下安裝boost.python, apt-get install libboost-python-dev
#include boost/python.hpp
char const* greet()
{
return "hello, world";
}
BOOST_PYTHON_MODULE(hello)
{
using namespace boost::python;
def("greet", greet);
}
把代碼存為hello.cpp, 編譯成so庫
g++ hello.cpp -o hello.so -shared -I/usr/include/python2.5 -I/usr/lib/python2.5/config -lboost_python-gcc42-mt-1_34_1
此處python路徑設為你的python路徑, 并且必須加-lboost_python-gcc42-mt-1_34_1, 這個庫名不一定是這個, 去/user/lib查
然后在有此so庫的目錄, 進入python, 可以如下使用
import hello
hello.greet()
'hello, world'
4. python 調用 c++ (ctypes)
ctypes is an advanced ffi (Foreign Function Interface) package for Python 2.3 and higher. In Python 2.5 it is already included.
ctypes allows to call functions in dlls/shared libraries and has extensive facilities to create, access and manipulate simple and complicated C data types in Python - in other words: wrap libraries in pure Python. It is even possible to implement C callback functions in pure Python.
#include Python.h
class TestFact{
public:
TestFact(){};
~TestFact(){};
int fact(int n);
};
int TestFact::fact(int n)
{
if (n = 1)
return 1;
else
return n * (n - 1);
}
extern "C"
int fact(int n)
{
TestFact t;
return t.fact(n);
}
將代碼存為wrapper.cpp不用寫python接口封裝, 直接編譯成so庫,
g++ -fPIC wrapper.cpp -o example.so -shared -I/usr/include/python2.6 -I/usr/lib/python2.6/config
進入python, 可以如下使用
import ctypes
pdll = ctypes.CDLL('/home/ubuntu/tmp/example.so')
pdll.fact(4)
12
在函數(shù)聲明加入前綴,如
__declspec(dllexport) int Fun(int a, int b)
否則在加載該dll時會提示找不到該符號
在windows下可以通過vs自帶的dumpbin工具查看可被調用符號
dumpbin /exports test.dll
C函數(shù)在調用過程中關于參數(shù)傳遞和壓棧由多種規(guī)定,作為dll提供給其他程序調用時,必須明確并統(tǒng)一為同一種調用規(guī)定,否則會導致棧破壞,編譯器負責具體實現(xiàn)調用規(guī)定,主要有以下幾種調用規(guī)定
python下調用C庫有多種方式,ctypes是其中一種比較方便的,調用時首先需要加載dll文件,根據(jù)C dll的調用規(guī)定不同需要使用不同接口,使用ctypes需要 import ctypes 庫
對于簡單的C函數(shù),例如 int add(int a, int b) , 此時就可以直接調用了,如
對于較復雜的C函數(shù)的參數(shù)情況,ctypes調用時對入參和出餐做一定處理,這里分情況討論
以上包含了幾種主要的參數(shù)傳遞情況,ctypes也提供了一個較為完整的python類型和C類型的對照,如下:
網站題目:python靜態(tài)庫c函數(shù) python c庫
URL標題:http://jinyejixie.com/article20/dodhgjo.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供定制開發(fā)、全網營銷推廣、服務器托管、網頁設計公司、網站制作、App開發(fā)
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)