Ⅰ 怎樣讓python腳本與C++程序互相調用
二、Python調用C/C++
1、Python調用C動態鏈接庫
Python調用C庫比較簡單,不經過任何封裝打包成so,再使用python的ctypes調用即可。
(1)C語言文件:pycall.c
[html] view plain
/***gcc -o libpycall.so -shared -fPIC pycall.c*/
#include <stdio.h>
#include <stdlib.h>
int foo(int a, int b)
{
printf("you input %d and %d\n", a, b);
return a+b;
}
(2)gcc編譯生成動態庫libpycall.so:gcc -o libpycall.so -shared -fPIC pycall.c。使用g++編譯生成C動態庫的代碼中的函數或者方法時,需要使用extern "C"來進行編譯。
(3)Python調用動態庫的文件:pycall.py
[html] view plain
import ctypes
ll = ctypes.cdll.LoadLibrary
lib = ll("./libpycall.so")
lib.foo(1, 3)
print '***finish***'
(4)運行結果:
2、Python調用C++(類)動態鏈接庫
需要extern "C"來輔助,也就是說還是只能調用C函數,不能直接調用方法,但是能解析C++方法。不是用extern "C",構建後的動態鏈接庫沒有這些函數的符號表。
(1)C++類文件:pycallclass.cpp
[html] view plain
#include <iostream>
using namespace std;
class TestLib
{
public:
void display();
void display(int a);
};
void TestLib::display() {
cout<<"First display"<<endl;
}
void TestLib::display(int a) {
cout<<"Second display:"<<a<<endl;
}
extern "C" {
TestLib obj;
void display() {
obj.display();
}
void display_int() {
obj.display(2);
}
}
(2)g++編譯生成動態庫libpycall.so:g++ -o libpycallclass.so -shared -fPIC pycallclass.cpp。
(3)Python調用動態庫的文件:pycallclass.py
[html] view plain
import ctypes
so = ctypes.cdll.LoadLibrary
lib = so("./libpycallclass.so")
print 'display()'
lib.display()
print 'display(100)'
lib.display_int(100)
(4)運行結果:
3、Python調用C/C++可執行程序
(1)C/C++程序:main.cpp
[html] view plain
#include <iostream>
using namespace std;
int test()
{
int a = 10, b = 5;
return a+b;
}
int main()
{
cout<<"---begin---"<<endl;
int num = test();
cout<<"num="<<num<<endl;
cout<<"---end---"<<endl;
}
(2)編譯成二進制可執行文件:g++ -o testmain main.cpp。
(3)Python調用程序:main.py
[html] view plain
import commands
import os
main = "./testmain"
if os.path.exists(main):
rc, out = commands.getstatusoutput(main)
print 'rc = %d, \nout = %s' % (rc, out)
print '*'*10
f = os.popen(main)
data = f.readlines()
f.close()
print data
print '*'*10
os.system(main)
(4)運行結果:
4、擴展Python(C++為Python編寫擴展模塊)
所有能被整合或導入到其它python腳本的代碼,都可以被稱為擴展。可以用Python來寫擴展,也可以用C和C++之類的編譯型的語言來寫擴展。Python在設計之初就考慮到要讓模塊的導入機制足夠抽象。抽象到讓使用模塊的代碼無法了解到模塊的具體實現細節。Python的可擴展性具有的優點:方便為語言增加新功能、具有可定製性、代碼可以實現復用等。
為 Python 創建擴展需要三個主要的步驟:創建應用程序代碼、利用樣板來包裝代碼和編譯與測試。
(1)創建應用程序代碼
[html] view plain
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int fac(int n)
{
if (n < 2) return(1); /* 0! == 1! == 1 */
return (n)*fac(n-1); /* n! == n*(n-1)! */
}
char *reverse(char *s)
{
register char t, /* tmp */
*p = s, /* fwd */
*q = (s + (strlen(s) - 1)); /* bwd */
while (p < q) /* if p < q */
{
t = *p; /* swap & move ptrs */
*p++ = *q;
*q-- = t;
}
return(s);
}
int main()
{
char s[BUFSIZ];
printf("4! == %d\n", fac(4));
printf("8! == %d\n", fac(8));
printf("12! == %d\n", fac(12));
strcpy(s, "abcdef");
printf("reversing 'abcdef', we get '%s'\n", \
reverse(s));
strcpy(s, "madam");
printf("reversing 'madam', we get '%s'\n", \
reverse(s));
return 0;
}
上述代碼中有兩個函數,一個是遞歸求階乘的函數fac();另一個reverse()函數實現了一個簡單的字元串反轉演算法,其主要目的是修改傳入的字元串,使其內容完全反轉,但不需要申請內存後反著復制的方法。
(2)用樣板來包裝代碼
介面的代碼被稱為「樣板」代碼,它是應用程序代碼與Python解釋器之間進行交互所必不可少的一部分。樣板主要分為4步:a、包含Python的頭文件;b、為每個模塊的每一個函數增加一個型如PyObject* Mole_func()的包裝函數;c、為每個模塊增加一個型如PyMethodDef MoleMethods[]的數組;d、增加模塊初始化函數void initMole()。
Ⅱ python怎樣嵌入c
用c語言編寫一個動態庫,提供兩個函數,兩個數的整形求和,兩個浮點數的求和。取名為mylib.c。
將c函數文件編譯成so動態庫。運行gcc mylib.c -fPIC -shared -o libtest.so命令,在目錄下可以看到生成的庫文件libtest.so。
Python調用so庫文件。首先導入ctypes,其次用CDLL載入so文件,最後調用對應的函數。將python代碼保存到pydemo.py中。
執行python pydemo.py查看運行結果。
眾多python培訓視頻,盡在python學習網,歡迎在線學習!
Ⅲ python怎麼和C或者C++混合編程
不難的,就是一個套路,主要是3步:
1.把Python的數據類型轉換為C/C++支持的數據類型;
2.調用C/C++函數,得到結果;
3.將結果轉換為Python支持的數據類型,返回。
相當於寫個中間層。
Ⅳ c語言和python兩種編譯器可以共存嗎
可以的,兩個編程語言的編譯器不沖突的。
C語言的邊編譯器可以使用visual studio 2008 / 2010 / 2012等。
python 編譯器直接網路搜索 python去官網即可下載。
其實, 不僅僅是這兩種語言,包括其他語言,也都可以安裝在同一電腦上的。
甚至可以說, 同一語言的不同版本也是可以共存的(比如C語言編譯器可以同時安裝 Visual studio 2008 和 Visual studio 2012)。
望採納, 謝謝。
Ⅳ 怎麼樣才能在c程序中嵌入python而不用依賴系統安裝的python而運行。也說是說怎麼把pyth
這個思路不是很行得通。。建議題主再思考一下程序結構。
為何要在C程序中嵌入python呢?
windows下,如果是一個獨立的python腳本,可以用py2exe轉換成一個可獨立運行的exe。因此如果能把python代碼分離出來,問題就簡單了。
Ⅵ 求助 關於c程序中嵌入Python的問題
嵌入
與python的擴展相對,嵌入是把Python解釋器包裝到C的程序中。這樣做可以給大型的,單一的,要求嚴格的,私有的並且(或者)極其重要的應用程序內嵌Python解釋器的能力。一旦內嵌了Python,世界完全不一樣了。
C調用python中的函數:
hw.py:
#coding=utf8
def hw_hs(canshu):
return canshu
if __name__ == "__main__":
ccss = "I am hw"
print hw_hs(ccss)
helloWorld.py:
#coding=utf8
import hw
def hello():
ccss = "I am helloWorld"
return hw.hw_hs(ccss)
if __name__ == "__main__":
print hello()
testcpypy.c:
//#include "testcpypy.h"
#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
//初始化Python
Py_Initialize();
if (!Py_IsInitialized()) {
printf("Py_Initialize");
getchar();
return -1;
}
//執行python語句
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
PyObject *pMole = NULL;
PyObject *pFunc = NULL;
PyObject *reslt =NULL;
//載入python模塊
if(!(pMole = PyImport_ImportMole("helloWorld"))) {
printf("PyImport_ImportMole");
getchar();
return -1;
}
//查找函數
pFunc = PyObject_GetAttrString(pMole, "hello");
if ( !pFunc || !PyCallable_Check(pFunc) )
{
printf("can't find function [hello]");
getchar();
return -1;
}
//調用python中的函數
reslt = (PyObject*)PyEval_CallObject(pFunc, NULL);
//printf("function return value : %d\r\n", PyInt_AsLong(reslt));
//將python返回的對象轉換為C的字元串
char *resltc=NULL;
int res;
res = PyArg_Parse(reslt, "s", &resltc);
if (!res) {
printf("PyArg_Parse");
getchar();
return -1;
}
printf("resltc is %s", resltc);
getchar();
//釋放內存
Py_DECREF(reslt);
Py_DECREF(pFunc);
Py_DECREF(pMole);
//關閉python
Py_Finalize();
return 0;
}
編譯:
gcc -o testcpypy testcpypy.c -IC:\Python27\include -LC:\Python27\libs -lpython27 ---C:\Python27為python安裝目錄
或:
gcc -c testcpypy.c -IC:\Python27\include
gcc -o testcpypy.exe testcpypy.o -LC:\Python27\libs -lpython27
執行結果:
帶參數的情況:
#include "callpydll.h"
#include "Python.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
int callhello(char *instr, char *outstr)
{
PyObject *pMole = NULL;
PyObject *pFunc = NULL;
PyObject *reslt = NULL;
PyObject *pParm = NULL;
char *resltc = NULL;
int resltn;
int res;
char *helloWorld = "TestIM_ProtocBuf";
char *im_account = "aaaa";
char *auth_code = "aaaa";
char *im_uid = "aaaa";
char *proxy_topic = "";
//初始化Python
Py_Initialize();
if (!Py_IsInitialized()) {
printf("Py_Initialize");
getchar();
return -1;
}
//執行python語句
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
//載入python模塊
if(!(pMole = PyImport_ImportMole(helloWorld))) {
printf("PyImport_ImportMole");
getchar();
return -2;
}
//查找函數
pFunc = PyObject_GetAttrString(pMole, "login_proxy_body_serialize");
if ( !pFunc || !PyCallable_Check(pFunc) )
{
printf("can't find function [hello]");
getchar();
return -3;
}
//參數轉換C --> python, 參數必須是元組(一個參數也是,否則會失敗!!!坑啊)
pParm = Py_BuildValue("(ssss)", im_account, auth_code, im_uid, proxy_topic);
//調用python中的函數
reslt = (PyObject*)PyEval_CallObject(pFunc, pParm);
//將python返回的對象轉換為C的字元串
res = PyArg_ParseTuple(reslt, "si", &resltc, &resltn);
if (!res) {
printf("PyArg_Parse");
getchar();
return -4;
}
printf("resltn is %d", resltn);
memcpy(outstr, resltc, strlen(resltc)+1);
//釋放內存
Py_DECREF(reslt);
Py_DECREF(pFunc);
Py_DECREF(pMole);
Py_DECREF(pParm);
//關閉python
Py_Finalize();
return 0;
}
int main() {
int i;
char *dais = "iammain";
char res[10240];
memset(res,'\0',sizeof(res));
i = callhello(dais, res);
if(0 != i) {
printf("Notify:error");
getchar();
return -1;
}
printf("result is %s", res);
getchar();
return 0;
}
Ⅶ 如何讓python調用C和C++代碼
如何讓python調用C和C++代碼
安裝python後,會有一個chm格式的python手冊。要搞明白如何讓python調用C/C++代碼(也就是寫python的 extension),你需要征服手冊中的
<<Extending && embedding>>厚厚的一章。在昨天花了一個小時看地頭暈腦脹,仍然不知道如何寫python的extension後,查閱了一些其他 書籍,最終在<<Python Programming On Win32>>書中找到了教程。
下面記錄一下如何在visual studio 2005中,寫一段C/C++的MessageBox代碼,然後提供後python調用,最後的結果當然是顯示一個MessageBox.
1. 首先要明白的是,所謂的python擴展(也就是你提供給python的c/c++代碼,不一定是c/c++代碼,可以是其他語言寫的代碼)是一個 dll,並且這個dll放在本機python安裝目錄下的DLLs目錄下(譬如我機器上的路徑是:F:\Program Files\Python25\DLLs),假如我們接下來要寫的擴展mole名為mb,python調用的代碼為: import mb
mb.showMsg("Python's really amazing, I kindda love it!")
python怎麼找到我們的mb模塊呢?就是上面說的,我們要生成一個mb.dll,然後拷貝到Dlls目錄下面,為了區別普通的dll和python專用擴展的dll,我們的 mb.dll修改成mb.pyd(python dll)
2. 搭建環境,我們要使用python提供的c頭文件和lib庫來進行擴展的開發。 在vs 2005下點擊菜單 "工具"->"選項", 打開選項對話框,選擇"項目和解決方案->VC++目錄", 然後在右邊"顯示以下內容的目錄"得comboBox上選擇"包含文件」,添加python的include目錄(我的機器上是"F:\Program
Files\Python25\include"),然後選擇庫文件,添加python的libs目錄(我的機器上是"F:\Program Files\Python25\libs")。
既然擴展是一個dll,接下來我們要建立一個「動態鏈接庫」工程,然後開始寫代碼:
#include <python.h> //python.h是包含python一些定義的頭文件,在python的include目錄下 /*
我的python版本是2.5, 因為安裝python後它沒提供debug下的lib庫文件,因此你必須生成release版的dll,
想要生成dll版本的,你要到python官網上自己去下載python源代碼,當然你可以繼續生成release版本的dll,但dll中包含調試信息
*/
#pragma comment(lib, "python25.lib")
//先不管
static PyObject* mb_showMsg(PyObject* self, PyObject *args); /*
如果你的擴展是mb,那麼必須實現一個initmb函數,並且從dll中導出這個函數,但我們在python中調用import mb時,python會去dll里去調用
initmb函數,這個函數告訴python我們有些什麼函數,該怎麼告訴python我們有一個showMsg函數呢?下面詳解 */
//必須extern "C"下,這樣不會在C++編譯器里不會更改掉導出的函數名字,我第一次就犯了這樣的錯誤
extern "C" __declspec(dllexport) void initmb() { /*
當調用mb.showMsg("Python's really amazing, I kindda love it!")時, 相當於你告訴python我有一個showMsg函數,我們怎麼告訴python去調用我們dll里的mb_showMsg函數呢?技巧就是下面的方式, 定義一個字典數據結構,key => showMsg, value =>mb_showMsg,METH_VARARGS是函數調用方式,仔細查手冊吧 */
static PyMethodDef mbMethods[] = { {"showMsg", mb_showMsg, METH_VARARGS},
{NULL, NULL, NULL} /*sentinel,哨兵,用來標識結束*/ };
//告訴python我們的模塊名叫mb, 模塊包含的函數都在mbMethods字典里 PyObject *m = Py_InitMole("mb", mbMethods); } /*
接下來實現核心功能showMsg */
//第一個self參數我們用不著,具體查手冊,第二個參數是python傳給我們的參數,它是一個python的參數tuple
static PyObject* mb_showMsg(PyObject* self, PyObject *args) {
//我們的showMsg函數需要的是一個字元串參數 const char* msg = NULL; /*
調用特殊參數解碼python傳遞給我們的參數,s是string,我們傳遞接收參數的變數地址,
如果你的功能函數需要兩個參數,在PyArg_parseTuple後面繼續添加接受參數的變數地址,
這個函數的原型是類似printf的不定參數的形式
PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *, const char *, ...); */
if (!PyArg_ParseTuple(args, "s", &msg)) return NULL;
//調用MB
int r = ::MessageBox(NULL, "hello", "Caption:Form C mole", MB_ICONINFORMATION | MB_OK);
//返回值
return Py_BuildValue("i", r); }
將上面這段混雜著大量注釋的代碼拷貝到你的編輯器里,然後編譯生成mb.dll,修改後綴成mb.pyd,然後拷貝到python的DLLs目錄下,打開idle(python的交互程序),寫入代碼: import mb
mb.showMsg("Python's really amazing, I kindda love it!")
可以看到彈出來一個MessageBox。
Ⅷ 如何實現C與python混合編程
實現C與python混合編程方法
代碼如下:
/* tcpportping.c */
#include <Python.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
/* count time functions */
static double mytime(void)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) == -1)
return 0.0;
return (double)tv.tv_usec + (double)tv.tv_sec * 1000000;
}
static PyObject * /* returns object */
tcpping(PyObject *self, PyObject *args )
{
struct sockaddr_in addr;
struct hostent *hp;
double time;
char *host = NULL;
int fd;
int port, timeout;
if (!PyArg_ParseTuple(args, "sii", &host, &port, &timeout)) /* convert Python -> C */
return NULL; /* null=raise exception */
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
return Py_BuildValue("d", -1.0); /* convert C -> Python */
}
bzero((char *)&addr, sizeof(addr));
if ((hp = gethostbyname(host)) == NULL) {
return Py_BuildValue("d", -2.0); /* convert C -> Python */
}
b(hp->h_addr, &addr.sin_addr, hp->h_length);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = timeout * 1000;
double stime = mytime();
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
return Py_BuildValue("d", -3.0); /* convert C -> Python */
}
fd_set read, write;
FD_ZERO(&read);
FD_ZERO(&write);
FD_SET(fd, &read);
FD_SET(fd, &write);
if (select(fd + 1, &read, &write, NULL, &tv) == 0) {
close(fd);
return Py_BuildValue("d", -4.0); /* convert C -> Python */
}
double etime = mytime();
time = etime - stime;
if (!FD_ISSET(fd, &read) && !FD_ISSET(fd, &write)) {
close(fd);
return Py_BuildValue("d", -4.0); /* convert C -> Python */
}
close(fd);
return Py_BuildValue("d", time/1000); /* convert C -> Python */
}
/* registration table */
static struct PyMethodDef portping_methods[] = {
{"tcpping", tcpping, METH_VARARGS}, /* method name, C func ptr, always-tuple */
{NULL, NULL} /* end of table marker */
};
/* mole initializer */
void inittcpportping( ) /* called on first import */
{ /* name matters if loaded dynamically */
(void) Py_InitMole("tcpportping", portping_methods); /* mod name, table ptr */
}
Ⅸ c可以調用python嗎
可以的。
C中內嵌Python
新建立一個工程,首先需要將工作目錄設置到Python-3.1.1PCbuild中,以獲取到動態庫,至於靜態庫的包含,Include目錄的指定,那自然也是少不了的。文件中需要包含Python.h文件,這也是必須的。
介面中
Py_Initialize();
Py_Finalize();
其他的根據需求,再引入相應的python builder 即可
Ⅹ 怎樣把Python代碼嵌入到C程序
步驟1:安裝Python開發包
由於需要訪問Python/C API,首先安裝Python開發包。
在Debian,Ubuntu或Linux Mint中:
在CentOS,Fedora或RHEL中:
安裝成功後,Python頭文件在/usr/include/python2.7。根據Linux發行版的不同,確切的路徑可能是不相同的。例如,CentOS 6中是/usr/include/python2.6。
步驟2:初始化解釋器並設置路徑
C中嵌入Python的第一步是初始化Python解釋器,這可以用以下C函數完成。
初始化解釋器後,需要設置你的C程序中要導入的Python模塊的路徑。例如,比如你的Python模塊位於/usr/local/moles。然後使用以下C函數調用來設置路徑。
步驟3:數據轉換
C中嵌入Python最重要的方面之一是數據轉換。從C中傳遞數據到Python函數,需要首先將數據從C數據類型轉換到Python數據類型。Python/C API提供各種函數來實現這。例如,轉換C字元串到Python字元串,使用PyString_FromString函數。
另外一個類似函數PyInt_FromLong,將C中long數據類型轉換為Python int。每個Python/C API函數返回一個PyObject類型的引用。
步驟4:定義一個Python模塊
當你想嵌入Python代碼到另一種語言如C,該代碼需要被寫成Python模塊,然後用另一種語言「導入」。所以讓我們來看看如何在C中導入Python模塊。
為了進行說明,我們實現一個簡單的Python模塊例子如下:
以上的Python函數有一個字元串作為參數並返回兩個重復的字元串。例如,如果輸入字元串是「cyberpersons」,該函數返回'cyberpersonscyberpersons'。此模塊文件命名為「printData.py」並將它放在前面聲明的Python模塊目錄中(/usr/local/moles)。
步驟5:載入一個Python模塊
現在你已經定義了Python模塊,是時候在C程序中載入它了。導入模塊的C代碼看起來像這樣:
步驟6:構建函數的參數
當載入一個模塊時,可以調用模塊中定義的Python函數。通常,我們需要傳遞一個或多個參數到一個Python函數。我們必須構建一個Python元組對象,它包括Python函數中的參數。
在我們的例子中,printData函數定義帶一個參數的模塊。因此,我們構建一個大小是一的Python元組對象如下。我們可以使用PyTuple_SetItem設置元組對象的每個項。
我們已經成功構建一個參數傳遞到函數調用,是時候從C程序調用python函數了。
步驟7:調用Python函數
一旦成功創建Python元組對象作為函數參數,我們可以調用一個帶參數的Python函數。為此,通過使用PyObject_GetAttrString首先獲得模塊中定義的函數的引用,然後使用PyObject_CallObject調用該函數。例如:
步驟8:錯誤檢查
避免運行時錯誤的常見方法是檢查函數的返回值並根據返回值採取適當的行動。類似於C程序中的全局變數errno,Python/C API提供一個全局指示符,它報告最後發生的錯誤。當Python/C API函數失敗,全局指示符設置為指示錯誤,並且PyErr_Print可以用於顯示相應的人類可讀的trackback。例如:
在你的應用程序中,你可以輕松地將各種錯誤檢查。
這里是完整的C程序,它如本教程描述的嵌入Python代碼。
步驟9:編譯和執行
保存以上代碼到finalCode.c,並且鏈接Python庫(-lpython2.7)編譯該代碼。根據發行版的不同,可能使用不同的版本(例如,-lpython2.6)。