vs生成dll的学习

By admin at 2020-01-07 • 0人收藏 • 2301人看过

之前都是用dll , 最近可能需要提供dll给别人, 那么dll怎么生成呢?

bilibili上面有很多这类视频教程 , 以下是自己记录自己学习的路.

image.png


image.png

image.png

在打开的writedll.cpp里面, 模仿上面的写法,写add()函数

image.png

然后, 去h头文件里添加这个add函数,

右键点击头部那个 include<writedll.h> ,选择打开那个h文件

image.png

继续模仿上面给出的示例, 写入add函数

image.png

保存, 右键点击工程头,选择编译生成dll , 

image.png

生成成功提示:

image.png

我们去debug目录里找到那个dll

image.png

这样就生成了一个简单的dll , 里面有封装add()这个函数, 以后别的程序可以调用这个dll来使用这个add函数了

7 个回复 | 最后更新于 2020-09-23
2020-01-07   #1

用dll函数查看工具查看下刚刚生成的dll ,

image.png

这里面的add函数名字加了@@这样的乱七八糟的东西, 为什么?

据说是c++的特性导致, 编译的时候会动态修改函数名....

那么我们可以添加一些限制给编译器, 不让他修改, 在writedll.h头文件里添加

image.png

#ifdef __cplusplus
extern "C" {
#endif

//你原来的导出函数

#ifdef __cplusplus
}
#endif

用上面的语句判断下是不是c++环境,  是就执行C格式导出, 其实就是添加了一对大括号

extern "C" {

    //你原来的导出函数

}

然后,保存, 重新生成dll

再次用dll函数查看器查看函数

image.png

现在对应起来了

至于上面的那些看着像是乱码的函数, 嗯... 删除cpp里面的导出类和h文件里面的导出类即可

image.png


2020-01-07   #2

下面用aardio调用下这个dll中的add函数, 看看是不是能用

image.png

import win.ui;
/*DSG{{*/
mainForm = win.form(text="aardio工程8";right=657;bottom=421)
mainForm.add()
/*}}*/


import console
console.open()


var dll = ..raw.loadDll("\res\Wrtiedll.dll","dllshare","cdecl");

console.log( dll.add(3,4) )

mainForm.show();
return win.loopMessage();

运行后可以看到:

image.png

同样调用示例的函数

image.png

2020-01-07   #3

dll中调用dll应该怎么写 ?( 封装dll为另外一个dll)

按照之前的方法, 新建一个win32的dll工程includedll

然后 , 把楼上之前生成的writedll.dll / writedll.h / writedll.Lib 这三个文件复制到刚刚新建的工程目录文件夹里面

image.png

然后在打开的includedll.cpp文件里添加

#include "Wrtiedll.h"
#pragma comment(lib,"Wrtiedll.lib")
// 这是导出函数的一个示例。
INCLUDEDLL_API int fadd(void)
{
    return add(43,56);
}

删掉原来的那些个声明函数, 修改后如下图

image.png

然后去includedll.h头文件那里把这个fadd()函数给声明下

image.png

保存工程, 编译,生成dll

image.png

成功了. 

下面用aardio调用下这个dll试试看

把这个生成的includedll.dll复制到上面的aardio工程里面

import console
console.open()

var dll = ..raw.loadDll("\res\includedll.dll",,"dllshare","cdecl");
console.log( dll.fadd() )

运行后出错误了.

image.png

提示说这个dll不能被加载,,,,...................

正常的,肯定会出错, 因为这个dll里面调用了另外一个dll里面的方法函数, 那么需要把被调用的那个writedll.dll也复制到同一个目录里去

image.png

再次运行, ok了

image.png

2020-03-16   #4

如果需要生成stdcall约定的dll, 那么在下面这个地方设置

捕获.PNG

这样设置完成后, 编译出来的dll又会变成乱码的样式, 那么我们就需要用.def文件来定义导出函数

点击项目右键->项目->新建项,

image.png

def文件内容如下:

第一行后面的名字必须和生成的dll同名

第二行是导出的关键词

后面是需要导出的函数名

注意:使用def文件的话就不需要在h头文件里定义之前那些,按照c语言那样直接写函数即可。


image.png

2020-09-15   #5

c++编写的dll中使用多线程

需要用_beginthreadex 和_endthreadex来创建和销毁线程

用上面函数产生的句柄, 并不会自动销毁, 需要最后手动CloseHandle下.

使用上面函数需要引用 process.h 头文件


下面我再dll中声明一个函数, 里面无限循环一个变量进行自加, 另外一个函数用来获取这个变量当前值. C++的代码如下:

#include "stdafx.h"
#include "process.h"

INT gloablNum = 0;
HANDLE hSendThread;
UINT WINAPI loopInit(PVOID pM) {
		while (true)
		{
			gloablNum++;
			Sleep(1000);
			if (gloablNum>=5000)
			{
				break ;
			}
		}
		//必须加,防止内存泄漏
		_endthreadex(0);
		//失败返回0
		return 0;
}

void startInit(void) {
        //开启并返回句柄
	hSendThread = (HANDLE)_beginthreadex(NULL, 0, loopInit, NULL, 0, NULL);
}

INT getNum(void) {
	return gloablNum;
}

void endClose(void) {
        //手动关闭句柄
	CloseHandle(hSendThread);
}

于是编译为dll之后, 在aardio中调用:

import console
console.open()
var dll = raw.loadDll("C:\threadTest\Debug\threadTest.dll",,"cdecl");
startInit = dll.api("startInit","void()" );
getNum = dll.api("getNum","INT()" );
endClose = dll.api("endClose","void()" );

winform.button.oncommand = function(id,event){
	startInit();
}

winform.button2.oncommand = function(id,event){
	console.log(getNum())
}

winform.onClose = function(hwnd,message,wParam,lParam){
    endClose();
}

blob.png


多线程中传递参数的方法:

#include "pch.h"
#include "process.H"

using namespace std;

typedef struct touchArg
{
	int		touchChannel = 1;
	bool scc;
}touchARG;


UINT WINAPI touchloop(PVOID pM) {
	touchARG* pa = (touchARG*)pM;
	int		touchChannel = pa->touchChannel;

	if (touchChannel>5)
	{
		pa->scc = true;
	}
	else
	{
		pa->scc = false;
	}
	pa->touchChannel = touchChannel;
	//必须加,防止内存泄漏
	_endthreadex(0);
	//失败返回0
	return 0;
}
// 端面接触 等待完成
bool test(int powerChannel) {
	touchARG s;
	s.touchChannel = powerChannel;
	s.scc = false;
	HANDLE htouchThread = (HANDLE)_beginthreadex(NULL, 0, touchloop, (LPVOID)&s, 0, NULL);
	WaitForSingleObject(htouchThread, INFINITE);
	CloseHandle(htouchThread);
	return s.scc;
}



2020-09-23   #6

C++编写dll : 如何生成dll中的回调函数

  1. 首先在cpp中声明个函数指针

  2. 设置外部函数指针给上面的函数指针

  3. 使用刚刚重置后的函数

CPP代码如下:

#include "stdafx.h"

int (*fcallback)(int data);

void setCallback(int(*Pfcallback)(int data)) {
	fcallback = Pfcallback;
}

int getCallback(int data) {
	int temp = fcallback(data);
	temp += data;
	return temp;
}

导出文件.def代码如下:

LIBRARY "testCallback"
	EXPORTS
	setCallback
	getCallback

上面把需要外部调用的两个函数给从dll中导出, 供其他软件调用


下面我用aardio来调用这个dll验证一下:

import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=351;bottom=208)
winform.add(
button={cls="button";text="Button";left=67;top=61;right=275;bottom=136;z=1}
)
/*}}*/

import console; 
var dll = raw.loadDll("/testCallback.dll",,"cdecl");
gCallback = dll.api("getCallback","int(int)" )
scallback = dll.api("setCallback","void(pointer)" )
//声明一个准备给dll重置的函数
var fun = function(data){
	var tep = 55;
	return 55;
}
//转换为函数指针
var Pfun = raw.tocdecl(fun,"int(int)");
//通过dll导出的这个函数给dll内部重置这个函数
scallback(Pfun);
//调用测试下
console.log(gCallback(3));
winform.button.oncommand = function(id,event){
        //改变变量再次测试
	console.log(gCallback(7));
}

winform.show();
win.loopMessage();

blob.png

符合预期.

2020-09-23   #7

那么是不是可以直接把上面生成的Thraddll中多线程函数和CallbackDll联合起来使用呢?

当然也是可以的, 在aardio中示例如下:

aar里将两个dll进行关联, 然后就可以愉快的进行使用了.

import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=507;bottom=346)
winform.add(
button={cls="button";text="Button";left=300;top=272;right=508;bottom=347;z=1};
button2={cls="button";text="init";left=35;top=142;right=170;bottom=179;z=2};
button3={cls="button";text="read";left=192;top=142;right=327;bottom=179;z=3}
)
/*}}*/

import console; 
console.open()
//回调的dll
var dll = raw.loadDll("/testCallback.dll",,"cdecl");
gCallback = dll.api("getCallback","int(int)" )
scallback = dll.api("setCallback","void(pointer)" )
//多线程的dll
var Testdll = raw.loadDll("/threadTest.dll",,"cdecl");
startInit = Testdll.api("startInit","void()" );
getNum = Testdll.api("getNum","INT()" );
endClose = Testdll.api("endClose","void()" );

//将多线程里面的函数和回调的函数进行关联
scallback(getNum);

winform.button.oncommand = function(id,event){
        //调用测试一下
	console.log(gCallback(7));
}

winform.button3.oncommand = function(id,event){
	console.log(getNum())
}

winform.button2.oncommand = function(id,event){
        //初始化多线程dll
	startInit();
}

winform.onClose = function(hwnd,message,wParam,lParam){
    endClose();
}

winform.show();
win.loopMessage();

blob.png

登录后方可回帖

登 录
信息栏
 私人小站

本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网


才仁机械


网站地图SiteMap

Loading...