實現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 */
}
2. Python編譯器推薦
1、CPython
是Python語言規范的參考實現,能夠優先獲得Python語言的最新、最強的功能,CPython是由C語言編寫而成,不但可以從Python代碼中調用C代碼的函數,還可以直接在Python中使用大量現有的C代碼庫。
2、Brython
Brython可用於在瀏覽器中運行包含了Python 3腳本的Web應用。
3、PyPy Python
雖然第一個推薦的是在Python中使用最廣泛的編譯器,但卻不是最快的,PyPy採用的是即時的編譯概念,在代碼執行前,就直接編譯為機器代碼,因此其執行速度提高了近4倍。
4、Jython或JPython
使用率第二高,Jython最初被稱為JPython,是通過Python語言來實現Java虛擬機的,開發者既可以將現有的Java包和代碼庫,導入自己的Python程序中,還可以在Java程序中嵌入Python腳本。
5、Cython
Cython與CPython不同,更像是一個超集,允許開發者在代碼中結合C和Python,從而生成C語言代碼類型的輸出,以供任何一種C/C++編譯器進行後續編譯。
6、Skulpt
流行的速度非常快,主要目的是提供一種良好的在線式Python編譯器,也可以通過讓Web應用引擎包含Skulpt,以方便開發者編寫出被用於前端的Python腳本。
7、PyJS
是另一款完全用Python去開發Web應用的編譯工具,在後台,PyJS會在使用內置的Ajax框架之前,將Python代碼編譯為JavaScript。
8、WinPython
是Python的"即用型"發行版,也就意味著用戶無需安裝,即可在Windows
PC上運行,作為另一種Python的實現,WinPython編譯器不僅帶來了Python執行環境,而且還包含了諸如:Scipy、Numpy、以及Pandas等各種Python庫。
3. pypy如何把python的py文件編譯成c代碼
pypy是用python實現的python,區別於cPython,和C沒什麼關系,你要用python寫C,需要的是Cython。具體看文檔,沒那麼難。
4. 有沒有能把python代碼轉換為c語言代碼的工具
C++兼容C語言,但C語言不可能兼容C++
所以,C++代碼直接轉是轉不了C的。
只能從邏輯上,對C++的許多語法進行代碼上的重新實現。
比如將對象轉換為結構體,將對象封裝的函數修改為獨立函數,增加對象參數。
將重載去掉,而是根據需要調用非重載的不同名的函數。
總之來說,硬要將C++轉為C實現的話,那代碼重寫的工作是避免不了的。
5. py的實現方式都有哪些
py指的是python嗎?
雖然官方 Python 實現差不多得到最廣泛的歡迎,但也有一些其他實現對特定領域的用戶來說更具吸引力。
知名的實現包括:
CPython
這是最早出現並持續維護的 Python 實現,以 C 語言編寫。新的語言特性通常在此率先添加。
Jython
以 Java 語言編寫的 Python 實現。此實現可以作為 Java 應用的一個腳本語言,或者可以用來創建需要 Java 類庫支持的應用。想了解更多信息可訪問 Jython 網站。
Python for .NET
此實現實際上使用了 CPython 實現,但是屬於 .NET 託管應用並且可以引入 .NET 類庫。它的創造者是 Brian Lloyd。想了解詳情可訪問 Python for .NET 主頁。
IronPython
另一個 .NET 的 Python 實現,與 Python.NET 不同點在於它是生成 IL 的完全 Python 實現,並且將 Python 代碼直接編譯為 .NET 程序集。它的創造者就是當初創造 Jython 的 Jim Hugunin。想了解詳情可訪問 IronPython 網站。
PyPy
完全使用 Python 語言編寫的 Python 實現。它支持多個其他實現所沒有的高級特性,例如非棧式支持和 JIT 編譯器等。此項目的目標之一是通過允許方便地修改解釋器 (因為它是用 Python 編寫的),鼓勵該對語言本身進行試驗。想了解詳情可訪問 PyPy 項目主頁。
以上這些實現都可能在某些方面與此參考文檔手冊的描述有所差異,或是引入了超出標准 Python 文檔范圍的特定信息。請參考它們各自的專門文檔,以確定你正在使用的這個實現有哪些你需要了解的東西。
6. 如何將python編譯成C代碼
好像只有pypy項目的rpython語言(python的一個子集)可以轉成c,幾乎沒有實際用途。
7. 如何讓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。
8. python擴展的c代碼在哪裡寫
在哪裡寫都可以啊,重要的是編譯過程。給你介紹下編譯過程吧。
在windows和linux下面,對C擴展的編譯方法是不一樣的,我們先來看windows版的。
我們用C實現一個簡單的加法。
首先新建一個文件add.c,代碼如下:
#include<Python.h>;
staticPyObject*add(PyObject*self,PyObject*args);
//一定聲明為static,把他們限制在這個文件范圍里。幾乎所有的參數都是PyObject類型,在python,每個東西都是object。
staticPyObject*add(PyObject*self,PyObject*args)
{
intx=0;
inty=0;
intz=0;
if(!PyArg_ParseTuple(args,"i|i",&x,&y))
returnNULL;
/*第一個參數是self,這個是python用的,每個函數都要有。我們暫時不管。args是一個參數列表。她把所有的參數都整合成一個string。所以
我們需要從這個string里來解析我們的參數。PyArg_ParseTuple來完成這個任務。第一個參數是args,就是我們要轉換的參數。第二個是格式符號。
「s」代表是個string。從args里提取一個參數就寫"s",兩個的話就寫"s|s",如果是一個string,一個int,就寫"s|i",和printf差不多。第三個
參數就是提取出來的參數放置的真正位置。必須傳遞這個參數的地址。對於add,他將提取兩個參數。分別是x和y。*/
z=x+y;
returnPy_BuildValue("i",z);
/*調用完之後我們需要返回結果。這個結果是c的type或者是我們自己定義的類型。必須把他轉換成PyObject,讓python認識。這個用Py_BuildValue
來完成。他是PyArg_ParseTuple的逆過程。他的第一個參數和PyArg_ParseTuple的第二個參數一樣,是個格式化符號。第三個參數
是我們需要轉換的參數。Py_BuildValue會把所有的返回只組裝成一個tutple給python。*/
}
staticPyMethodDefaddMethods[]=
{
{"add",add,METH_VARARGS,"Executeashellcommand."},
{NULL,NULL,0,NULL}
};
/*這個是一個c的結構。他來完成一個映射。我們需要把我們擴展的函數都映射到這個表裡。表的第一個欄位是python真正認識的。是python里的方法名字。第二個欄位是python里的這個方法名字的具體實現的函數名。在python里調用add,真正執行的是用c寫的add函數。第三個欄位是METH_VARARGS,他告訴python,add是調用c函數來實現的。第四個欄位是這個函數的說明。如果你在python里來help這個函數,將顯示這個說明。相當於在python里的函數的文檔說明。*/
PyMODINIT_FUNCinitadd()
{
Py_InitMole("add",addMethods);
}
/*注意,這個函數的名字不能改動。必須是init+模塊名字。我們的模塊名字是add。所以這個函數是initadd()。
這樣python在導入add的模塊時候,才會找到這個函數,並調用。這個函數調用Py_InitMole來將模塊名字和映射表結合在一起。他表示,add這個模塊使用addMethods這個映射表。python應該這樣導入我們的mole的.*/
新建一個setup.py,內容如下:
fromdistutils.coreimportsetup,Extension
mole1=Extension('add',sources=['add.c'])
setup(name='PackageName',version='1.0',description='Thisisademopackage',ext_moles=[mole1])
組建:(由於我的機器上裝了mingw,所以指定了mingw32。默認的編譯器是vs2008。參考:
python setup.py build--compiler=mingw32
執行後會在當前目錄生成一個build目錄及文件:
buildlib.win32-2.6add.pyd
將add.pyd拷貝到當前目錄,並寫一個測試文件test.py,代碼如下:
import add
print add.add(3,4)
執行一下,輸出為7
OK,基本上就是如此了。
在linux下的話,會有少許不同.
即直接用makefile將add.c編譯成.so,python可以直接import,makefile代碼如下:
PYLIB=/usr/bin
PYINC=/usr/include/python2.6
all:add.c
gccadd.c-g-I$(PYINC)-shared-L$(PYLIB)-lpython2.6-oadd.so
clean:
rm-fadd.so
用同樣的測試代碼,可以測試通過。
9. python是用c寫的嗎
python是用c寫的,下面給大家介紹一下Python與c的聯系:
python的誕生
1991年,第一個Python編譯器(同時也是解釋器)誕生。它是用C語言實現的,並能夠調用C庫(.so文件)。從一出生,Python已經具有了:類(class),函數(function),異常處理(exception),包括表(list)和詞典(dictionary)在內的核心數據類型,以及模塊(mole)為基礎的拓展系統。
Guido希望有一種語言,這種語言能夠像C語言那樣,能夠全面調用計算機的功能介面,又可以像shell那樣,可以輕松的編程。ABC語言讓Guido看到希望。ABC是由荷蘭的CWI (Centrum Wiskunde & Informatica, 數學和計算機研究所)開發的。Guido在CWI工作,並參與到ABC語言的開發。ABC語言以教學為目的。與當時的大部分語言不同,ABC語言的目標是「讓用戶感覺更好」。ABC語言希望讓語言變得容易閱讀,容易使用,容易記憶,容易學習,並以此來激發人們學習編程的興趣。
相關推薦:《Python基礎教程》
python與c
Python語法很多來自C,但又受到ABC語言的強烈影響。來自ABC語言的一些規定直到今天還富有爭議,比如強制縮進。但這些語法規定讓Python容易讀。另一方面,Python聰明的選擇服從一些慣例(特別是C語言的慣例)。比如使用等號賦值,使用def來定義函數。Guido認為,如果「常識」上確立的東西,沒有必要過度糾結。
Python從一開始就特別在意可拓展性(extensibility)。Python可以在多個層次上拓展。從高層上,你可以引入.py文件。在底層,你可以引用C語言的庫。Python程序員可以快速的使用Python寫.py文件作為拓展模塊。但當性能是考慮的重要因素時,Python程序員可以深入底層,寫C程序,編譯為.so文件引入到Python中使用。Python就好像是使用鋼構建房一樣,先規定好大的框架。而程序員可以在此框架下相當自由的拓展或更改。
最初的Python完全由Guido本人開發。Python得到Guido同事的歡迎。他們迅速的反饋使用意見,並參與到Python的改進。Guido和一些同事構成Python的核心團隊。他們將自己大部分的業余時間用於hack Python (也包括工作時間,因為他們將Python用於工作)。隨後,Python拓展到CWI之外。Python將許多機器層面上的細節隱藏,交給編譯器處理,並凸顯出邏輯層面的編程思考。Python程序員可以花更多的時間用於思考程序的邏輯,而不是具體的實現細節 (Guido有一件T恤,寫著:人生苦短,我用Python)。這一特徵吸引了廣大的程序員。Python開始流行。
python的發展
到今天,Python的框架已經確立。Python語言以對象為核心組織代碼(Everything is object),支持多種編程範式(multi-paradigm),採用動態類型(dynamic typing),自動進行內存回收(garbage collection)。Python支持解釋運行(interpret),並能調用C庫進行拓展。Python有強大的標准庫 (battery included)。由於標准庫的體系已經穩定,所以Python的生態系統開始拓展到第三方包。這些包,如Django, web.py, wxpython, numpy, matplotlib,PIL.
Python從其他語言中學到了很多,無論是已經進入歷史的ABC,還是依然在使用的C和Perl,以及許多沒有列出的其他語言。可以說,Python的成功代表了它所有借鑒的語言的成功。同樣,Ruby借鑒了Python,它的成功也代表了Python某些方面的成功。每個語言都是混合體,都有它優秀的地方,但也有各種各樣的缺陷。同時,一個語言「好與不好」的評判,往往受制於平台、硬體、時代等等外部原因。
10. 如何利用python實現類似c語言的共同體
import ctypes #你可以看看ctypes,它可以支持union,下面是一個例子
from ctypes import ( Union, Array,
c_uint8, c_uint32,
cdll, CDLL
)
class uint8_array(Array):
_type_ = c_uint8
_length_ = 4
class u_type(Union):
_fields_ = ("data", c_uint32), ("chunk", uint8_array)
# load printf function from Dynamic Linked Libary libc.so.6 (I'm use linux)
libc = CDLL(cdll.LoadLibrary('libc.so.6')._name)
printf = libc.printf
if __name__ == "__main__": # initialize union
_32bitsdata = u_type() # set values to chunk
_32bitsdata.chunk[:] = (1, 2, 3, 4) # and print it
printf(b"Data in 32 bits: %d\n", _32bitsdata.data)