日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

小结两种在Python中导入C语言扩展库的方法

發布時間:2025/3/15 python 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小结两种在Python中导入C语言扩展库的方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

小結兩種在Python中導入C語言擴展庫的方法

分類:?Pythoner?2563人閱讀?評論(1)?收藏?舉報 python擴展c語言importstring

一種是Python文檔的推薦方案,采用C API擴展寫法:

在D:建一個add.c文件,輸入

[cpp]?view plaincopy
  • //add.c??
  • ??
  • //??
  • ??
  • #include?<Python.h>;??
  • ??
  • static?PyObject*?add(PyObject?*self,?PyObject?*args);???
  • //一定聲明為static,把他們限制在這個文件范圍里。?幾乎所有的參數都是PyObject類型。?在python,每個東西都是object。???
  • ??
  • static?PyObject*?add(PyObject*?self,?PyObject*?args)???
  • {???
  • ???int?x=0?;???
  • ???int?y=0;??
  • ???int?z=0;??
  • ?if?(!?PyArg_ParseTuple(args,?"i|i",?&x,?&y))??
  • ??return?NULL;??
  • ?/*第一個參數是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;??
  • return?Py_BuildValue("i",?z);??
  • ????/*調用完之后我們需要返回結果。這個結果是c的type或者是我們自己定義的類型。必須把他轉換成PyObject,?讓python認識。這個用Py_BuildValue??
  • ?來完成。他是PyArg_ParseTuple的逆過程。他的第一個參數和PyArg_ParseTuple的第二個參數一樣,?是個格式化符號。第三個參數??
  • ?是我們需要轉換的參數。Py_BuildValue會把所有的返回只組裝成一個tutple給python。*/??
  • }???
  • ??
  • static?PyMethodDef?addMethods[]?=??
  • {???
  • ???{"add",??add,?METH_VARARGS,?"Execute?a?shell?command."},???
  • ???{NULL,?NULL,?0,?NULL}??
  • };???
  • /*這個是一個c的結構。他來完成一個映射。?我們需要把我們擴展的函數都映射到這個表里。表的第一個字段是python真正認識的。是python??
  • 里的方法名字。?第二個字段是python里的這個方法名字的具體實現的函數名。?在python里調用add,?真正執行的是用c寫的add函數。?
  • 第三個字段是METH_VARARGS,?他告訴python,add是調用c函數來實現的。第四個字段是這個函數的說明。如果你在python里來help這個函數,?
  • 將顯示這個說明。相當于在python里的函數的文檔說明。*/??
  • ??
  • PyMODINIT_FUNC?initadd()???
  • {???
  • ???????Py_InitModule("add",?addMethods);???
  • }???
  • /*注意,這個函數的名字不能改動。?必須是init+模塊名字。?我們的模塊名字是add。所以這個函數是initadd()。?
  • 這樣python在導入add?的模塊時候,才會找到這個函數,并調用。這個函數調用Py_InitModule來將模塊名字和映射表結合在一起。??
  • 他表示,add這個模塊使用addMethods這個映射表。python應該這樣導入我們的module的.*/??
  • ?

    然后在D:盤建立setup.py

    [python]?view plaincopy
  • from?distutils.core?import?setup,?Extension??
  • ??
  • module1?=?Extension('add',?sources?=?['add.c'])??
  • ??
  • setup?(name?=?'PackageName',?version?=?'1.0',?description?=?'This?is?a?ADD?package',?ext_modules?=?[module1])??
  • ?

    將cmd切換到D:

    輸入setup.py build --compiler=mingw32 -verbose

    這里我選擇了mingw32,否則在我的機器上它會用msvc,而這會有一些小錯誤

    運行成功后會在(當前目錄的)D:/build/lib.win32-2.6下生成add.pyd

    ?

    下面就在Python中導入

    >>> import sys
    >>> sys.path.append("D:/build/lib.win32-2.6")

    >>> import add
    >>> add.add(3,2)
    5

    ?

    Bingo!

    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

    ?

    以上是用C API的擴展方式,它的寫法比較麻煩。以下用ctypes直接導入dll模塊。

    ?

    如果是在Windows下面:

    首先在D:建立文件spam.c

    [cpp]?view plaincopy
  • //spam.c??
  • ??
  • //??
  • ??
  • #include?<windows.h>??
  • ??
  • BOOL?APIENTRY??
  • DllMain(HANDLE?hModule,?DWORD?dwReason,?LPVOID?lpReserved)??
  • {??
  • ?return?TRUE;??
  • }??
  • ??
  • __declspec(dllexport)?int??
  • multiply(int?num1,?int?num2)??
  • {??
  • ?return?num1?*?num2;??
  • }??
  • ??
  • //這是一個標準的Windows?DLL的寫法。??
  • ?

    我用cl來編譯它,現在我漸漸喜歡上了用cl來編譯,省得建一個好幾兆的項目,而且參數可以靈活選擇。后面我會繼續學習如何寫make file。

    在cmd輸入cl -I"d:/programs/python26/include" spam.cpp,會生成spam.obj

    再輸入link spam.obj /DLL /libpath:"d:/programs/python26/libs",生成spam.dll

    ?

    下面到python中導入:

    >>> import ctypes
    >>> cdll=ctypes.cdll.LoadLibrary('d:/spam.dll')

    >>> cdll.multiply(2,3)
    6

    ?

    如果是在Linux下面:

    在/home/Henry下建立spam.c

    [cpp]?view plaincopy
  • char?*foo(){?????
  • ????char?*p?=?"hello?world";?????
  • ????return?p;?????
  • }?????
  • ????
  • void?foo1(char?*p){?????
  • ????strcpy(p,?"hello?world");?????
  • }????
  • 編譯:$ gcc -o libspam.so -fpic -shared spam.c

    進入Python:

    [python]?view plaincopy
  • #返回指針:???
  • >>>?import?ctypes???
  • >>>?hello?=?ctypes.cdll.LoadLibrary("/home/Henry/libspam.so")???
  • >>>?p?=?hello.foo()??
  • >>>?ctypes.c_char_p(p).value???
  • >>>?'hello?world'???
  • ??
  • #傳入buffer:???
  • >>>?b?=?ctypes.create_string_buffer(12)???
  • >>>?hello.foo1(b)???
  • >>>?b.value???
  • >>>?'hello?world'???
  • %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    ?

    但是ctypes對C++的DLL導入不行。對于C++庫的導入還是要借助于Boost.python。

    我一定會回來的!

    總結

    以上是生活随笔為你收集整理的小结两种在Python中导入C语言扩展库的方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。