c/c++编写dll供其他语言调用
范例
就以md5為例吧,首先去github搜索md5,選一個用c或者c++寫的md5.
比如:https://github.com/chinaran/Compute-file-or-string-md5
我試了下用dev c++運行main_md5.c文件沒什么問題。不過代碼中計算文件md5的函數有點問題,先不管他,就演示一下計算字符串的。
Dev c++
首先說一下怎么用dev寫一個dll
左上角->文件->新建->項目
選擇DLL,下面選擇C項目,項目名隨便,就叫md5吧。然后選擇一個空文件夾,即可創建dll項目
其他默認創建的dll.h文件內容:
這全部的代碼其實就一句__declspec(dllexport) void HelloWorld();。聲明HelloWorld函數并設置為導出函數。
將上面github地址代碼下載下來,有三個文件md5.h、md5.c、main_md5.c。
將這三個文件中的內容稍微整合一下到dll.h、dll.c和dllmain.c中,下面有整合之后的代碼
接著點上面的編譯運行,編譯完會彈出一個警告,沒有主程序,不用管它,看項目的目錄下的文件,已經有個md5.dll了
這個就是要用其他語言調用的dll,以Python為例(注意修改dll路徑)
運行一下成功得到結果:
另外需要注意的是,如果在64位系統上dev C++編譯的dll是64位的。需要使用64位Python才能調用。如果用的是32位則會報如下異常(32位dll同理)
百度了很久也沒有發現dev c++怎么在64位系統編譯32位dll,我試了直接更改右上角gcc的版本沒用,換成32位的會報錯。
代碼地址:https://gitee.com/kanadeblisst/dev-c-dll-md5/
vs2017
要想編譯32位的只能使用vs2017來編譯了, 怎么安裝就省略了,安裝vs2019也行,可能某些操作不太一樣。
左上角文件->新建項目
選擇這個visual C++下的 Windows桌面下的具有導出項的動態鏈接庫(記得修改上面的路徑,不然你都不知道去哪找項目文件),如果沒有這個選項可能你功能沒有安裝完全。我安裝的時候是把Windows下的三個都勾選了,選擇的社區版,只需要登錄賬號即可使用,功能對我來說足夠用了。
代碼基本上一樣,復制到vs里就行了。就是不知道為什么他一定要pch.h這個頭文件,改了名就報錯。這篇文章說了:https://blog.csdn.net/weixin_43074474/article/details/89520392
我就直接將代碼復制到pch.h和pch.cpp了,另外還有個地方需要修改__declspec(dllexport) 前要加上extern “C” ,不然導出函數的名字會變成其他了,前后加上了點東西(dev c++如果創建的是C++項目也是一樣的)
用32位Python試了下上面的Python代碼調用,沒啥問題。
vs默認編譯的是32位的dll,如果想編譯64位的直接將x86改成x64再點擊一次本地Windows調試器生成的dll就是64位的了
同樣的代碼vs編譯的dll要比dev c++的小好多,到底是微軟自家的IDE,不過dev c++用來測試一些簡單的c/c++代碼是真的方便。
更新
突然看到一篇文章:https://blog.csdn.net/songyi160/article/details/50754705
說將x86前的debug改為Release,我試了試,其他沒變。就是編譯的dll從原來的60K變成了14K,這變化也太大了吧
代碼:https://gitee.com/kanadeblisst/vs2017-md5-dll
下一篇:編寫aes加解密的dll
aardio調用dll
這個語言寫桌面程序非常方便,我用的很順手,就順便說說這個怎么調用dll。注意:aardio只能調用32的dll
import console;var dll = raw.loadDll("D:\Android\Dll3\Debug\DLL3.dll",,"cdecl" );var md5 = dll.api("Compute_string_md5","int(string str,int len, string str)"); var s = "12345"; var str = raw.buffer(33);console.log("運行是否成功(0成功):", md5(s, #s, str)) console.log("md5結果: ", raw.tostring(str))console.pause(true);看著是不是和Python代碼差不了多少,步驟都是一樣的。加載dll->聲明函數原型->創建一個存放結果的緩沖區->調用函數->讀取緩沖區的值。
更新
編碼引發的小問題
md5 本身是對字節進行操作的,那么對字符串進行操作肯定要涉及編碼問題了。c語言在Windows的默認編碼是gbk,而Python3的默認編碼是utf-8,而我試了所有的網站,對字符串計算md5用的編碼都是utf8。
修改也很簡單,可以不修改c代碼,直接修改Python調用dll時的代碼,只需要改傳入的第二個參數,上面的代碼用的是字符串的長度,其實應該傳入字節串的長度,修改代碼如下
md5(ctypes.c_char_p(msg.encode()), ctypes.c_uint(len(msg.encode())), result)
在python3中,'aaaa'.encode()等同于 'aaaa'.encode('utf-8'),所以并不需要更改編碼,反倒是在c語言中將gbk編碼變成utf8的很麻煩。
其實修改c代碼也很簡單,因為第二個參數長度是不必要的,可以直接通過第一個參數用strlen計算出來,所以在c代碼中改一下也行。strlen計算的長度是從開頭開始到遇到的第一個字節0,即’\0’,正好是需要的長度。
編譯成Linux的so文件
我記得在哪里看到過這樣一句話,so其實就是沒有main函數的程序。
所以將上面的md5程序改成so很簡單,只需要去掉dll 的代碼,保留主要的pch.h和pch.cpp(在vs項目中我直接將md5的代碼寫在里面了),再把__declspec(dllexport)這個去掉,然后在Linux使用g++ -shared -fPIC -o md5.so pch.cpp。-o后面指定的是輸出的so文件名,然后是需要編譯的cpp文件。
用Python調用的代碼不變,dll = ctypes.CDLL("/root/md5.so"),改成so的路徑就行了。
不過怎么在64位Linux編譯32位的so,我還沒搜到。有些說加-m32參數,我試的時候報錯了,大概意思是缺少某些32位的依賴庫。
總結
以上是生活随笔為你收集整理的c/c++编写dll供其他语言调用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 社保html源码,社保查询.html
- 下一篇: C++上机报告 利用公式计算π=4(1-