1. 程式人生 > 程式設計 >Qt程式中呼叫C#編寫的dll(推薦)

Qt程式中呼叫C#編寫的dll(推薦)

1、開啟Visual Studio,新建一個C#的Class Library專案(這裡選擇的是.Net Framework 4),專案名為CSharpDll。

Qt程式中呼叫C#編寫的dll(推薦)

2、由於預設沒有引入Forms等UI庫,先在reference中新增引用System.Windows.Forms以便可以在測試中使用MessageBox等。

Qt程式中呼叫C#編寫的dll(推薦)

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,而把計算結果通過ref引數c給返回),一個showBox方法(裡面採用C#的MessageBox對話方塊顯示使用者輸入的引數字串)

4、對project進行release build,在release目錄下生成了CSharpDll.dll(待會用到)。

5、關閉CSharpDll專案,另外新建一個C++ CLR型別的Class Library專案(選擇與C#專案相同的.Net Framework 4),專案名稱為CppDll。

Qt程式中呼叫C#編寫的dll(推薦)

一開始我用的VS2019,發現VS2019好像無法新建 C++ CLR型別的Class Library專案了,所以學習微軟的技術一定要小心,學習主流的支援很久的技術,儘量不要學習新出的技術,如果必須學新技術,一定要認真考量,一些邊緣化的技術一定不要學習,沒準哪天微軟就不維護了。

6、選擇Project->CppDll Properties…,在彈出的屬性頁面選擇“Add New Reference..”,點選“browsing.”後選擇CSharpDll專案中release目錄下的CSharpDll.dll。

Qt程式中呼叫C#編寫的dll(推薦)

7、選擇CSharpDll.dll後,可以看到在專案屬性的References中出現了CSharpDll這個Library。

8、在CppDll專案中的CppDll.h中利用 _declspec(dllexport)匯出對應的3個介面函式add,substract,showBox 。需要using namespace System::Reflection,對於這裡的showBox,其引數不能採用CSharpDll裡面的showBox引數的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 *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資料夾中了。

Qt程式中呼叫C#編寫的dll(推薦)

10、接下來在Qt中進行呼叫, 在QtCreator中新建一個TestCSharpDll GUI專案,編譯器選的mingw。通過VS自帶的命令列工具中的dumpbin工具可以檢視CppDll.dll匯出的函式介面。

dumpbin -exports (+dll路徑)

Qt程式中呼叫C#編寫的dll(推薦)

在TestCSharpDll工程中通過typedef定義函式指標,同時採用QLibrary動態載入並resolve函式。

在這裡.dll的路徑設為當前目錄下“./CppDllMingW.dll”,也就是編譯好的程式exe同一目錄下的dll,去resolve由普通匯出方式的介面即“?add@@YAHHH@Z”。

主要程式碼如下所示:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QLibrary>
#include<QMessageBox>
typedef int (*x_add)(int a,int b);
typedef void (*x_substract)(int a,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,&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複製到同一目錄下,執行TestCSharpDll.exe,可看出點選按鈕後,通過QLibrary進行動態resolve,均正常呼叫。

Qt程式中呼叫C#編寫的dll(推薦)

呼叫add函式

Qt程式中呼叫C#編寫的dll(推薦)

呼叫sub函式

Qt程式中呼叫C#編寫的dll(推薦)

呼叫showBox函式

最好是將相關dll置於同一目錄下執行,不然會出現“未能載入檔案或程式集”的異常。針對.lib連結方式,理應是置於同一目錄下。而針對QLibrary進行resolve方式,可能通常一開始的想法是,CppDll.dll和CSharpDll.dll放在與程式不同目錄的地方,程式中利用了QLibrary指定了CppDll.dll的方式進行載入,而CppDll.dll和CSharpDll.dll,因此程式呼叫CppDll.dll裡面的函式時,CppDll.dll會找到與CppDll.dll同一目錄下的CSharpDll.dll,然而CppDll.dll在被程式進行載入時,其繼承了程式的環境變數,因此會從程式的當前目錄下去查詢,所以最好還是將CppDll.dll和CSharpDll.dll放置於程式同一目錄下,同時QLibrary載入當前目錄下的CppDll.dll。當然,部署到另外一臺機器上時,目標機器還是需要安裝.Net Framework,其版本至少不能低於當前CSharpDll.dll所使用的版本。

總結

到此這篇關於Qt程式中呼叫C#編寫的dll的文章就介紹到這了,更多相關Qt 呼叫C#編寫的dll內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!