python作為一種膠水和c c

2021-09-25 06:12:27 字數 3214 閱讀 1563

如果需要用 python 呼叫 c/c++ 編寫的第三方庫,只需要乙個指令碼語言來粘合它們。這個時候,用 python ctypes 可以很方便地實現呼叫。

stackoverflow 上的 calling c/c++ from python 這個主題介紹了 ctypes 最簡單的入門方法,概括如下:

如果是 c 函式庫,則直接 load 這個庫,然後呼叫即可;

如果是 c++ 函式庫,則需要用 extern 關鍵字封裝乙個供 c 使用的函式,即把類隱藏到一些 c 風格的函式裡,然後用 extern 標明這些函式,以方便外部呼叫。

這兩種方法裡,弄懂了 ctypes 呼叫 c++ 庫的方法,就會用 ctypes 呼叫 c 函式庫,對 c++ 庫的基本方法如下。

例如,有乙個 c++ 類 foo:

#includeclassfoo

};

再封裝出下面 c 風格的介面函式:

extern"c"voidfoo_bar(foo* foo)

}

g++ -c -fpic foo.cpp -o foo.o

g++ -shared -wl,-soname,libfoo.so -o libfoo.so foo.o

,然後再用 python 寫的**來呼叫這個類,你可以把上面兩個 c 介面函式寫成 python 類,或是直接呼叫:

from ctypes import cdll 

lib = cdll.loadlibrary('./libfoo.so')  

class foo(object):     

def __init__(self):         

self.obj = lib.foo_new()     

def bar(self):

lib.foo_bar(self.obj)

,然後就可以在 python 指令碼裡呼叫這個 python 類了:

f = foo()

f.bar() #and you will see "hello" on the screen

在 windows 下用 python ctypes 的方法和上面一樣,只是有下面兩點需要注意一下:

在編寫 python **時,剛開始鏈結所需的動態鏈結庫時,最好使用絕對路徑來 load,以減少出錯概率,加快除錯速度 在我按上面的方法編寫好了上述**時,一執行指令碼,則提示如下錯誤資訊:

$ python linkcpp.py

traceback (most recent call last):

file "linkcpp.py", line 2, in lib = cdll.loadlibrary('./linkexample')

file "c:\python27\lib\ctypes\__init__.py", line 431, in loadlibrary

return self._dlltype(name)

file "c:\python27\lib\ctypes\__init__.py", line 353, in __init__

self._handle = _dlopen(self._name, mode)

windowserror: [error 126]

from ctypes import cdll 

lib = cdll.loadlibrary('./linkexample')

如果把 ./linkexample 這句換成 windows 下的絕對路徑 e:/pythoncode/linkcpp/linkexample,則沒有錯誤提示了。當然,你直接把 ./linkexample 換成 linkexample 也可以找到該鏈結庫。

所以,剛開始的時候,使用絕對路徑,以確保你不會糾結於能不能找到鏈結庫之類的問題。

在執行上述指令碼的時候,出現 windowserror: [error 126] 的錯誤,無非就是兩個原因:

另外,注意一下,windows 下因為庫分為 lib 和 dll 兩個檔案,所以可以只輸入庫的名稱即可,比如說你要鏈結 linkexample.dll 庫,則可以在 ctypes 裡只需要宣告鏈結名為 linkexample 庫即可。

如果是 c++ 寫的庫,需要用上 extern 關鍵字,這個和一般的供 c 呼叫的 c++ 庫標頭檔案是一樣的 在 extern 宣告的函式裡,可以使用 c++ 裡 c 沒有的關鍵字,比如我的函式就是這樣宣告的:

externintlinkexample(constintindex,constchar* name);
上面**可以從 python 呼叫執行。

extern:extern可置於變數或者函式前,以表示變數或者函式的定義在別的檔案中,提示編譯器遇到此變數或函式時,在其它模組中尋找其定義。另外,extern也可用來進行鏈結指定。

親自實現

c++  

g++編譯 g++ -o libpycallclass.so -shared -fpic ex.cpp 

#include using

namespace

std;

class

testlib

; void

testlib::display()

void testlib::display(int

a)

extern"c

" void

display_int()

}

python 呼叫

import

ctypes

so =ctypes.cdll.loadlibrary

lib = so("

./libpycallclass.so

")

print

'display()

'lib.display()

print

'display(100)

'lib.display_int(100)

1 2 作為一種技術的演算法

要研究演算法,哪些指標可以用來衡量演算法的好壞呢?1.這個演算法要能正確解決問題。這個是前提,研究演算法的最終目的也是為了解決問題。如果乙個演算法,不能解決問題,那要它何用。2.這個演算法占用的資源應該盡可能小。計算機可以做得很快,但不能無限快。儲存器很便宜,但不會免費。計算時間是一種有限的資源,儲...

一種協程的 C C 實現

在前幾天接觸到了協程的概念,覺得很有趣。因為我可以使用乙個執行緒來實現乙個類似多執行緒的程式,如果使用協程來替代執行緒,就可以省去很多原子操作和記憶體柵欄的麻煩,大大減少與執行緒同步相關的系統呼叫。因為我只有乙個執行緒,而且協程之間的切換是可以由函式自己決定的。我有見過幾種協程的實現,因為沒有 c ...

C C 中switch用法的一種替換方式

在c c 中,switch語句是經常被用到的,當switch內的case語句較多時程式有時顯得比較繁亂,此種情況下可以用另外一種實現方式替代switch。詳細用法見例子 include stdafx.h float addfunc float a,float b float subfunc floa...