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

歡迎訪問 生活随笔!

生活随笔

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

python

python调用c++动态库

發(fā)布時間:2023/12/29 python 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python调用c++动态库 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

python調(diào)用C++動態(tài)庫

  • 生成C++動態(tài)庫
    • 1.編譯成64位的dll庫
    • 2. C++ 模板
    • 3. 示例
  • Python調(diào)用帶參數(shù)的動態(tài)庫
    • python與c數(shù)據(jù)類型
    • int、long、float、double參數(shù)
    • 參數(shù)聲明
    • 字符與字符串參數(shù)
    • C分配內(nèi)存與釋放內(nèi)存
  • python與c的效率

生成C++動態(tài)庫

生成C++ 動態(tài)庫需要注意以下幾點:

1.編譯成64位的dll庫

如果64位的python調(diào)用32位的dll會報下面的錯誤:

OSError: [WinError 193] %1 不是有效的 Win32 應用程序。

這種錯誤的原因基本上都是64為的python調(diào)用了32位的動態(tài)庫。
解決的方法是生成64位的動態(tài)庫。安裝了visual studio可以使用:

x64的命令行窗口進行編譯。編譯命令是:

cl /LD hello.cpp

2. C++ 模板

頭文件的模板如下:

//dll.h #ifndef DLL_EXPORT #define DECLDIR __declspec(dllimport) #else #define DECLDIR __declspec(dllexport) #endif

c++源文件的模板如下:

//hello.cpp #include "stdio.h" #include <iostream> #include <string.h>#ifdef __cplusplus extern "C" { #endif #define DLL_EXPORT #include "dll.h"using namespace std;#pragma execution_character_set("utf-8")DECLDIR void hello(void){printf("hello world");} DECLDIR int add_int(int a,int b){return a+b; } DECLDIR float add_float(float a,float b){return a+b; } DECLDIR double add_double(double a,double b){return a+b; } DECLDIR char pass_char(char c){printf("%c\n",char(c));return c; } DECLDIR wchar_t pass_wchar(wchar_t wc){wcout.imbue(locale("chs"));wcout<< wc;return wc; } DECLDIR char* pass_str(char *s){printf("%s\n",s);return strcat(s,"return"); } DECLDIR wchar_t* pass_wstr(wchar_t*s,wchar_t wc){wcout<< s;wchar_t *p = wcschr(s,wc);return p;}DECLDIR int* get_memory(int n) {int *p = new int[n];for(int i = 0; i < n; i++){p[i] = i;}return p; }DECLDIR void free_memory(int *p) {if(p)delete [] p; } DECLDIR int find_num(int target,int *p,int n){int i;for (i=0;i<n;i++){if (p[i]== target)return i;}return -1;}#ifdef __cplusplus } #endif

3. 示例

c++程序見第二節(jié)
python程序如下:

from ctypes import * lib_path = './hello.dll' dlllib = cdll.LoadLibrary(lib_path) dlllib.hello()

Python調(diào)用帶參數(shù)的動態(tài)庫

第一節(jié)的示例是沒有任何參數(shù)的,屬于最簡單的情況。如何傳遞以及返回參數(shù),才是python調(diào)用動態(tài)庫的要點。

python與c數(shù)據(jù)類型

在ctypes中定義python互相對應的參數(shù)類型。

類型pythonc
布爾c_boolbool
整型c_intint
長整型c_longlong
浮點c_floatfloat
雙精度c_doubledouble
字符c_charchar
寬字符c_wcharwchar_t
字符串c_char_pchar*
寬字符串c_wchar_pwchar_t *
指針c_void_pvoid *

int、long、float、double參數(shù)

標準的dll調(diào)用需要明確傳入?yún)?shù)和返回參數(shù),否則系統(tǒng)會默認為所有參數(shù)為整型。比如:

//hello.cpp #include "stdio.h" #include <iostream>#ifdef __cplusplus extern "C" { #endif #define DLL_EXPORT #include "dll.h"using namespace std;DECLDIR void hello(void){printf("hello world");} DECLDIR int add_int(int a,int b){return a+b; } DECLDIR float add_float(float a,float b){return a+b; } DECLDIR double add_double(double a,double b){return a+b; }#ifdef __cplusplus } #endif from ctypes import * lib_path = './hello.dll' dlllib = cdll.LoadLibrary(lib_path) ret_i =dlllib.add_int(1,200) ret_f = dlllib.add_float(c_float(1.1),c_float(2.1)) print(ret_i,ret_f)

此時程序返回的結果為:
201 1094533517

參數(shù)聲明

解決辦法是顯式聲明傳入和返回參數(shù)。

from ctypes import * lib_path = './hello.dll' dlllib = cdll.LoadLibrary(lib_path) ret_i =dlllib.add_int(1,200) dlllib.add_float.argtypes=[c_float,c_float] dlllib.add_float.restype = c_float ret_f = dlllib.add_float(c_float(1.1),c_float(2.1)) print(ret_i,ret_f)

此時結果為:

201 3.1999998092651367

字符與字符串參數(shù)

傳遞單個字符,可以使用c_char或者c_wchar,如果要傳遞字符串則需要c_char_p和c_wchar_p:

from ctypes import * lib_path = './hello.dll' dlllib = cdll.LoadLibrary(lib_path) dlllib.pass_char.argtypes=[c_char] dlllib.pass_char.restype = c_char ret_c = dlllib.pass_char(b"A") dlllib.pass_wchar.argtypes=[c_wchar] dlllib.pass_wchar.restype = c_wchar ret_w = dlllib.pass_wchar("學")dlllib.pass_str.argtypes=[c_char_p] dlllib.pass_str.restype = c_char_pret_s = dlllib.pass_str(b"test string ") dlllib.pass_wstr.argtypes=[c_wchar_p,c_wchar] dlllib.pass_wstr.restype = c_wchar_p ret_sw = dlllib.pass_wstr("世界真奇妙","好")print("------") print("pass_char",str(ret_c.decode("utf8"))) print("pass_wchar",ret_w) print("pass_str",str(c_char_p(ret_s).value.decode("utf8"))) print("pass_wstr",ret_sw)

需要注意的是,c++對寬字符的處理比較麻煩,如果返回的字符串被修改,需要特別注意,因為返回的可能是亂碼。

------ pass_char A pass_wchar 學 pass_str test string return pass_wstr 真奇妙 A 學test string 世界真奇妙

C分配內(nèi)存與釋放內(nèi)存

分配內(nèi)存后,返回的是一個指針。

from ctypes import * lib_path = './hello.dll' dlllib = cdll.LoadLibrary(lib_path) dlllib.get_memory.argtypes=[c_int] dlllib.get_memory.restype = POINTER(c_int) ret_int = dlllib.get_memory(20) print("get:",ret_int) int_array = [ret_int[i] for i in range(20)] print(int_array)dlllib.free_memory.restype = c_void_p dlllib.free_memory(ret_int) get: <__main__.LP_c_long object at 0x00000272E0718040> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

python與c的效率

使用python與C混合編程的意義在于C的處理速度快,畢竟python是解釋型語音。比如通過循環(huán)查找數(shù)組里面的數(shù)值:

from ctypes import * import line_profiler import sysdef c_find(a):lib_path = './hello.dll'dlllib = cdll.LoadLibrary(lib_path)dlllib.find_num.argtypes=[c_int,POINTER(c_int),c_int]dlllib.find_num.restype = c_intret_f = dlllib.find_num(5,a,len(a))return ret_fdef p_find(a):for i in range(len(a)):if a[i]==5:return ireturn -1def main():a = [20]*100000a.append(5)arr_d = (c_int * len(a))(*(i for i in a))lib_path = './hello.dll'dlllib = cdll.LoadLibrary(lib_path)dlllib.find_num.argtypes=[c_int,POINTER(c_int),c_int]dlllib.find_num.restype = c_intdlllib.find_num(5,arr_d,len(arr_d))p_find(a)profile = line_profiler.LineProfiler(main) profile.enable() main() profile.disable() profile.print_stats(sys.stdout)

結果:

Timer unit: 1e-07 sTotal time: 0.0549094 s File: p1.py Function: main at line 21Line # Hits Time Per Hit % Time Line Contents ==============================================================21 def main():22 1 3110.0 3110.0 0.6 a = [20]*10000023 1 2200.0 2200.0 0.4 a.append(5)24 1 299069.0 299069.0 54.5 arr_d = (c_int * len(a))(*(i for i in a))25 1 11.0 11.0 0.0 lib_path = './hello.dll'26 1 9016.0 9016.0 1.6 dlllib = cdll.LoadLibrary(lib_path)27 1 428.0 428.0 0.1 dlllib.find_num.argtypes=[c_int,POINTER(c_int),c_int]28 1 31.0 31.0 0.0 dlllib.find_num.restype = c_int29 1 1576.0 1576.0 0.3 dlllib.find_num(5,arr_d,len(arr_d))30 1 233653.0 233653.0 42.6 p_find(a)Process finished with exit code 0

數(shù)組的大小是100001個,要選擇的元素在最后一個。純查找時間python為233653個時間單位,而c為1576。當然傳遞數(shù)組需要很長的時間。這是額外的花銷。需要綜合考慮是否采用動態(tài)庫,因為參數(shù)準備與傳遞需要很大的花銷。

總結

以上是生活随笔為你收集整理的python调用c++动态库的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。