C#调用Qt编写的带界面的dll
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013482632/article/details/88829072
Qt编写带界面的dll
Qt编写的带界面的dll程序,由于Qt必须调用QApplication的exec方法才能运行,所以在普通windows程序中是不能调用的,Qt提供了解决方案qtwinmigrate。
-
开发环境
操作系统:win10
Qt Create版本:qt-creator-opensource-windows-x86-4.4.1.exe,下载地址:http://download.qt.io/archive/qt/4.8/4.8.6/
qtwinmigrate源码:从https://github.com/qtproject/qt-solutions下载的qtwinmigrate源码。 -
操作流程
1)从qtwinmigrate/examples中复制一份qtdll,重命名,比如“testdll”,文件夹里有一份main.cpp和pro文件;
2)用Qt Creator打开“testdll”下的pro文件,添加自己写的界面类文件,在pro文件中添加这些文件;
3)release模式下构建工程,会在qtwinmigrate\examples\build-testdll-unknown-Release\release文件夹下生成对应dll文件,该文件即可被C#程序调用。 -
代码演示
1)自己界面类构造函数
CTestDialog(HWND hParentWnd, QObject *parent = 0, Qt::WindowFlags f = 0);
CTestDialog::CTestDialog(HWND hParentWnd, QObject *parent, Qt::WindowFlags f)
:QDialog(0, f), hParent(hParentWnd)
{
if (parent)
QObject::setParent(parent);
}
2)main.cpp
#include <qmfcapp.h>
#include <windows.h>
#include "testDialog.h"//include自己的界面类文件
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpvReserved*/ )
{
static bool ownApplication = FALSE;
if ( dwReason == DLL_PROCESS_ATTACH )
ownApplication = QMfcApp::pluginInstance( hInstance );
if ( dwReason == DLL_PROCESS_DETACH && ownApplication )
delete qApp;
return TRUE;
}
// char* output用于给调用者返回数据,如:CTestDialog界面配置结果等
extern "C" __declspec(dllexport) bool showDialog( HWND parent, char* output )
{
std::string ret = "";
CTestDialog dialog(parent);
if (dialog.exec() == QDialog::Accepted)
ret = dialog.getResults();//dialog配置结果
strcpy_s(output, ret.length()+1, ret.c_str());
return TRUE;
}
注意:
1)需要将调用接口导出(extern “C” __declspec(dllexport));
2)如果调用的界面仅用于展示,不需要返回数据时,showDialog可采用如下实现方式:
extern "C" __declspec(dllexport) bool showDialog( HWND parent )
{
CTestDialog dialog(parent);
dialog.show();
return qApp->exec();
}
3)注意字符串的传递需要采用char*方式。
C#调用实现
-
开发环境
操作系统:win10
开发工具:VS2010 -
操作流程
1)新建项目,Visual C#–Windows,选择Windows窗体应用程序,修改项目名称和存储位置;
2)修改Form1.cs文件,引用构建的Qt的testdll.dll,运行即可出效果。 - 代码演示
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices; //必须添加,不然DllImport报错
namespace WindowsFormsTest
{
public partial class Form1 : Form
{
//"testdll\testdll.dll"是testdll.dll路径,可以是绝对路径和相对路径
[DllImport(@"testdll\testdll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
//output为testdll.dll返回的char*
public static extern bool showDialog(IntPtr parent, ref byte output);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
byte[] data = new byte[100];
bool ret = showDialog(this.Handle, ref data[0]);
string strGet = System.Text.Encoding.Default.GetString(data, 0, data.Length);
Console.WriteLine(strGet);//用vs运行时,strGet打印在VS的输出窗口中
}
}
}
注意:
1)Qt编写的dll文件移动位置时,需要将其依赖的库都拷出来一起移动,尤其是换了电脑之类的,否则运行将不成功。可用DEPENDS工具查看其依赖的库;
2)本处只演示了C#语言调用,C++调用时需要LoadLibary等,此处不再演示,读者可自行实验。
结果
运行C#程序后,界面弹出Qt编写的CTestDialog界面,如下图所示,涉及项目内容处均涂红了。
点击弹出的dialog的“确定”按钮时,测试程序中返回的字符串“test”打印在VS的输出窗口中,下图中红框框起来的部分,蓝色部分涉及个人信息,所以涂蓝了。