這篇文章主要介紹了Qt程序中怎么調(diào)用C#編寫的dll,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
成都創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的鄱陽網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
1、打開Visual Studio,新建一個C#的Class Library項目(這里選擇的是.Net Framework 4),項目名為CSharpDll。
2、由于默認(rèn)沒有引入Forms等UI庫,先在reference中添加引用System.Windows.Forms
以便可以在測試中使用MessageBox
等。
3、最終C#編寫的dll的源代碼如下圖所示,命名空間為CSharpDll,公共類為CSharpClass。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSharpDll { public class CSharpClass { public CSharpClass() { } public int add(int a , int b) { return a + b; } public void substract( int a , int b , ref int c) { c = a - b; } public static void showBox(string str) { MessageBox.Show("C#:" + str); } } }
里面包含一個加法add,一個減法substract(為了測試指針,所以在減法的返回類型是void,而把計算結(jié)果通過ref參數(shù)c給返回),一個showBox方法(里面采用C#的MessageBox對話框顯示用戶輸入的參數(shù)字串)
4、對project進行release build,在release目錄下生成了CSharpDll.dll
(待會用到)。
5、關(guān)閉CSharpDll項目,另外新建一個C++ CLR類型的Class Library項目(選擇與C#項目相同的.Net Framework 4),項目名稱為CppDll。
一開始我用的VS2019,發(fā)現(xiàn)VS2019好像無法新建 C++ CLR類型的Class Library項目了,所以學(xué)習(xí)微軟的技術(shù)一定要小心,學(xué)習(xí)主流的支持很久的技術(shù),盡量不要學(xué)習(xí)新出的技術(shù),如果必須學(xué)新技術(shù),一定要認(rèn)真考量,一些邊緣化的技術(shù)一定不要學(xué)習(xí),沒準(zhǔn)哪天微軟就不維護了。
6、選擇Project->CppDll Properties…,在彈出的屬性頁面選擇“Add New Reference..”,點擊“browsing.”后選擇CSharpDll項目中release目錄下的CSharpDll.dll。
7、選擇CSharpDll.dll后,可以看到在項目屬性的References中出現(xiàn)了CSharpDll這個Library。
8、在CppDll項目中的CppDll.h中利用 _declspec(dllexport)
導(dǎo)出對應(yīng)的3個接口函數(shù)add,substract,showBox 。需要using namespace System::Reflection,對于這里的showBox,其參數(shù)不能采用CSharpDll里面的showBox參數(shù)的String類型,而是使用const char* 類型。
主要代碼如下所示:
// CppDll.h #pragma once using namespace System; using namespace System::Reflection; __declspec(dllexport) int add(int a, int b) { CSharpDll::CSharpClass obj; return obj.add(a, b); } __declspec(dllexport) void substract(int a, int b, int *c) { CSharpDll::CSharpClass obj; obj.substract(a, b, *c); } __declspec(dllexport) void showBox(const char* content) { CSharpDll::CSharpClass obj; String^ str = gcnew String(content); obj.showBox(str); } namespace CppDll { public ref class Class1 { // TODO: 在此處添加此類的方法。 }; }
9、選擇release方式build CppDll項目,在release文件夾中生成了CppDll.dll文件,可以看到同時其也將引用的CSharpDll.dll也給拷貝到release文件夾中了。
10、接下來在Qt中進行調(diào)用, 在QtCreator中新建一個TestCSharpDll GUI項目,編譯器選的mingw。通過VS自帶的命令行工具中的dumpbin工具可以查看CppDll.dll導(dǎo)出的函數(shù)接口。
dumpbin -exports (+dll路徑)
在TestCSharpDll工程中通過typedef定義函數(shù)指針,同時采用QLibrary動態(tài)加載并resolve函數(shù)。
在這里.dll的路徑設(shè)為當(dāng)前目錄下“./CppDllMingW.dll”,也就是編譯好的程序exe同一目錄下的dll,去resolve由普通導(dǎo)出方式的接口即“?add@@YAHHH@Z”。
主要代碼如下所示:
#include "mainwindow.h" #include "ui_mainwindow.h" #include#include typedef int (*x_add)(int a , int b); typedef void (*x_substract)(int a , int b , int* c); typedef void (*x_showBox)(const char* content); MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } //add void MainWindow::on_pushButton_clicked() { int a = ui->lineEdit->text().toInt(); int b = ui->lineEdit_2->text().toInt(); QLibrary library("./CppDll.dll"); if(library.load()){ x_add add = (x_add)library.resolve("?add@@YAHHH@Z"); if(add){ QString str = QString::number(add(a , b)); QMessageBox::information(this , "call add from dll" , str); } } } //sub void MainWindow::on_pushButton_2_clicked() { int a = ui->lineEdit_3->text().toInt(); int b = ui->lineEdit_4->text().toInt(); int c = 0; QLibrary library("./CppDll.dll"); if(library.load()){ x_substract sub = (x_substract)library.resolve("?substract@@YAXHHPAH@Z"); if(sub){ sub(a , b , &c); QString str = QString::number(c); QMessageBox::information(this , "call sub from dll" , str); } } } //showBox void MainWindow::on_pushButton_3_clicked() { QLibrary library("./CppDll.dll"); if(library.load()){ x_showBox showBox = (x_showBox)library.resolve("?showBox@@YAXPBD@Z"); if(showBox){ showBox("showBox!"); } } }
編譯TestCSharpDll工程,將CppDll.dll和CSharpDll.dll復(fù)制到同一目錄下,執(zhí)行TestCSharpDll.exe,可看出點擊按鈕后,通過QLibrary進行動態(tài)resolve,均正常調(diào)用。
調(diào)用add函數(shù)
調(diào)用sub函數(shù)
調(diào)用showBox函數(shù)
最好是將相關(guān)dll置于同一目錄下運行,不然會出現(xiàn)“未能加載文件或程序集”的異常。針對.lib鏈接方式,理應(yīng)是置于同一目錄下。而針對QLibrary進行resolve方式,可能通常一開始的想法是,CppDll.dll和CSharpDll.dll放在與程序不同目錄的地方,程序中利用了QLibrary指定了CppDll.dll的方式進行加載,而CppDll.dll和CSharpDll.dll,因此程序調(diào)用CppDll.dll里面的函數(shù)時,CppDll.dll會找到與CppDll.dll同一目錄下的CSharpDll.dll,然而CppDll.dll在被程序進行加載時,其繼承了程序的環(huán)境變量,因此會從程序的當(dāng)前目錄下去查找,所以最好還是將CppDll.dll和CSharpDll.dll放置于程序同一目錄下,同時QLibrary加載當(dāng)前目錄下的CppDll.dll。當(dāng)然,部署到另外一臺機器上時,目標(biāo)機器還是需要安裝.Net Framework,其版本至少不能低于當(dāng)前CSharpDll.dll所使用的版本。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Qt程序中怎么調(diào)用C#編寫的dll”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!