DLL与EXE之间的通讯调用 以及 回调函数的线程执行空间
dll 与 exe 之间的通讯方式有很多种, 本文采用回调函数的方法实现, 本文也将研究多线程,多模块的情况下,回调函数所在的线程, 啥也不说了,先附上代码:
下面的是dll模块的的, dll的工程文件:
- library DllAPP;
- uses
- windows,
- SysUtils,
- Classes,
- DllClass in 'DllClass.pas';
- {$R *.res}
- var
- GDllServer: TDllServer;
- function AddServer(ADispatchFunc: TDispatchFunc): HRESULT; stdcall;
- begin
- Result := ERROR_INVALID_FUNCTION;
- if not Assigned(GDllServer) then
- Exit;
- GDllServer.AddServer(ADispatchFunc);
- Result := ERROR_SUCCESS;
- end;
- function DataDispatch(ACommand: Integer):HRESULT; stdcall;
- begin
- Result := ERROR_INVALID_FUNCTION;
- GDllServer.DataDispatch(ACommand);
- Result := 0;
- end;
- function DLLInitialize: HRESULT;
- begin
- Result := 1;
- GDllServer := TDllServer.create;
- Result := ERROR_SUCCESS;
- end;
- function DllFinalize: HRESULT;
- begin
- Result := ERROR_INVALID_FUNCTION;
- GDllServer.Free;
- GDllServer := nil;
- Result := ERROR_SUCCESS;
- end;
- exports
- AddServer,
- DataDispatch,
- DLLInitialize,
- DllFinalize;
- begin
- end.
dll中的类型文件
- unit DllClass;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TDispatchFunc = function(ACommand: Integer): HRESULT;stdcall;
- type
- TDLLSERVER = CLAss;
- TDLLThread = class(TThread)
- private
- FCount: Integer;
- FDllServer: TDllServer;
- public
- procedure Execute; override;
- public
- constructor create;
- end;
- TDllServer = class
- private
- FDispatchFunc: TDispatchFunc;
- FDllThread: TDLLThread;
- public
- procedure AddServer(ADispatchFunc: TDispatchFunc);
- procedure DataDispatch(ACommand: Integer);
- public
- constructor Create;
- destructor Destroy;
- end;
- implementation
- { TDllServer }
- ///保存exe的回调函数指针
- procedure TDllServer.AddServer(ADispatchFunc: TDispatchFunc);
- begin
- FDispatchFunc := ADispatchFunc;
- end;
- constructor TDllServer.create;
- var
- LThreadID: Cardinal;
- begin
- ///
- LThreadID := GetCurrentThreadid;
- ShowMessage('DLL,create:'+IntToStr(LThreadID));
- FDllThread := TDLLThread.create;
- FDllThread.FDllServer := Self;
- FDllThread.Resume;
- end;
- ///DLL接受exe传过来的指令, dll留给exe的调用借口
- procedure TDllServer.DataDispatch(ACommand: Integer);
- var
- LThreadID: Cardinal;
- begin
- if not Assigned(FDispatchFunc) then
- Exit;
- FDispatchFunc(ACommand);
- LThreadID := GetCurrentThreadid;
- ShowMessage('DLL,DateDispatch:'+IntToStr(LThreadID));
- end;
- destructor TDllServer.Destroy;
- begin
- ////
- end;
- { TDLLThread }
- constructor TDLLThread.create;
- var
- LThreadID: Cardinal;
- begin
- FCount := 0;
- inherited create(True);
- end;
- //这个函数的目的就是检验不同模块下的不同线程下,回调函数的执行线程
- procedure TDLLThread.Execute;
- var
- LThreadID: Cardinal;
- begin
- inherited;
- while not Terminated do
- begin
- Inc(FCount);
- if FCount = 2 then
- begin
- LThreadID := GetCurrentThreadid;
- ShowMessage('DLL,Thread--'+IntToStr(LThreadID));
- end;
- if FCount = 5 then
- begin
- if assigned(FDllServer) then
- begin
- FDllServer.FDispatchFunc(2);
- end;
- end;
- Sleep(1000);
- end;
- end;
- end.
exe的文件
- unit ExeClass;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TDispatchFunc = function (ACommand: Integer): HRESULT;stdcall;
- TServerFunc = function (ADispatchFunc: TDispatchFunc): HRESULT;stdcall;
- TProc = function: HRESULT;
- type
- TForm2 = class(TForm)
- Button1: TButton;
- Memo1: TMemo;
- procedure FormDestroy(Sender: TObject);
- procedure Button1Click(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- private
- { Private declarations }
- FServerDispatch: TServerFunc; ///exe--->dll
- FDataDispatch: TDispatchFunc; ///EXE--->DLL
- FDllInitialize: TProc;
- FDllFinalize: TProc;
- public
- { Public declarations }
- end;
- var
- Form2: TForm2;
- GHandleLibrary: THandle;
- GCount: Integer;
- implementation
- {$R *.dfm}
- ///DLL--->EXE,留给dll调用的回调函数
- function DataDispatch(ACommand: Integer): HRESULT; stdcall;
- var
- LThreadID: Cardinal;
- begin
- LThreadID := GetCurrentThreadid;
- ShowMessage('EXE:'+IntToStr(LThreadID));
- end;
- procedure TForm2.Button1Click(Sender: TObject);
- begin
- Inc(GCount);
- FDataDispatch(GCount);
- end;
- procedure TForm2.FormDestroy(Sender: TObject);
- begin
- FDllFinalize;
- FServerDispatch := nil;
- FDataDispatch := nil;
- FDllInitialize := nil;
- FDllFinalize := nil;
- FreeLibrary(GHandleLibrary);
- end;
- procedure TForm2.FormCreate(Sender: TObject);
- var
- LThreadID: Cardinal;
- begin
- GHandleLibrary := LoadLibrary(PChar('DLLAPP.dll'));
- @FDllInitialize := GetProcAddress(GHandleLibrary, 'DLLInitialize');
- @FDllFinalize := GetProcAddress(GHandleLibrary, 'DllFinalize');
- @FServerDispatch := GetProcAddress(GHandleLibrary, 'AddServer');
- @FDataDispatch := GetProcAddress(GHandleLibrary,'DataDispatch');
- FDllInitialize;
- FServerDispatch(DataDispatch);
- LThreadID := GetCurrentThreadid;
- Memo1.Lines.Add(IntToStr(LThreadID));
- end;
- end.
1,简单实现的dll与exe之间的通讯, 其实就是利用了dll的导出函数, 先想dll传递一个回调函数的地址,供dll面向exe的通讯。 exe面向dll 的通讯直接执行dll导出函数即可
2, 本文是最基本的实现,当然其中的回调函数,以及dll的处理函数,可以在数据包的级别上实现, 即: 定义不同数据包,根据命令执行不同的函数, 这样只要导出一个函数,保留一个回调函数 就可以实现大量的功能
3, 关于回调函数的线程执行空间,取决于调用者所在的线程, 比如dll线程中回调exe的函数, 则回调函数是执行在该dll线程。 如果是主线程执行回调,则在主线程。 上述代码GDLLclass的创建过程是导出函数,所以GDLLclass的主线程就是exe的主线程,他们在一个线程空间
http://blog.csdn.net/procedure1984/article/details/3985127
DLL与EXE之间的通讯调用 以及 回调函数的线程执行空间的更多相关文章
- Python并发编程06 /阻塞、异步调用/同步调用、异步回调函数、线程queue、事件event、协程
Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件event.协程 目录 Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件 ...
- [Effective JavaScript 笔记]第67条:绝不要同步地调用异步的回调函数
设想有downloadAsync函数的一种变种,它持有一个缓存(实现为一个Dict)来避免多次下载同一个文件.在文件已经被缓存的情况下,立即调用回调函数是最优选择. var cache=new Dic ...
- setInterval调用ajax回调函数不执行的问题
setInterval调用ajax回调函数不执行 1.首先检查你的setInterval()函数写法是否正确 参考写法 // 检查是否支付成功 var isPayRequest=false; var ...
- frameset,iframe框架之间如何互相调用变量、函数
以往一直在编写的都是前台的UI,很少使用到frameset.iframe,对其了解也是十分有限,只是知道其可以为其当前页面引入html文件成为当前页的一部分,但是这两天在做后台UI界面的时候,发现这样 ...
- C#调用C++回调函数的问题
C++的回调函数中有一个参数是,是返回一个字符串,原则如下: typedef void (*TDataEvent)(char *AData ,int ALen); 其中char ...
- (转载)spring 之间的远程调用-Spring Http调用的实现
原文:https://www.cnblogs.com/lewisat/p/6132082.html 1:Spring Http设计思想 最近在研究公司自己的一套rpc远程调用框架,看到其内部实现的设计 ...
- python 调用dll 动态链接库 结构体参数及回调函数等示例
结构体示例: 这里是 C 代码的部分,主要是结构体的声明和回调函数定义. // 新版本定义 typedef enum { DevCard, DevLocator, DevReader } DevTyp ...
- python处理多线程之间事件通讯方法
一.什么是事件 每执行一个事情,肯定有该事情的执行后状态,那事件就是该事情发生的信号 在程序中,多线程之间需要通讯,而事件就是方便线程之间的通讯 案例: 1.服务器启动需要5秒 2.客服端启动后去链接 ...
- Silverlight中异步调用WCF服务,传入回调函数
以前学的ASP.NET,调用的都是同步方法,同步方法的好处就是,一步一步走,完成这步才会走下一步.然而,WCF使用的都是异步方法,调用之后不管有没有获得结果就直接往下走,最可恶的是异步函数都是Void ...
随机推荐
- MongoDB 启动异常
今天启动MongoDB遇到异常状况 mongodb warning: 32-bit servers don't have journaling enable 解决方法: 删除数据库目录的.lock文件 ...
- java 正则表达式抽取
package com.achun.test; import java.util.regex.Matcher;import java.util.regex.Pattern; public class ...
- WCF---服务发布的步骤
服务发布的步骤: 1.打开你的VS2012网站项目,右键点击项目>菜单中 重新生成一下网站项目:再次点击右键>发布: 2.弹出网站发布设置面板,点击<新建..>,创建新的发布配 ...
- 并发编程:c++11 多线程中随机数重复问题
srand(time(NULL)); 是我们熟悉的c++随机函数,用时间做种子.但由于在多线程环境下若想在子线程中随机出不同的随机数则需随机种子的不同.但time以秒计算,略显不足,故参考这篇文章解决 ...
- hdu 4888 Redraw Beautiful Drawings 网络流
题目链接 一个n*m的方格, 里面有<=k的数, 给出每一行所有数的和, 每一列所有数的和, 问你能否还原这个图, 如果能, 是否唯一, 如果唯一, 输出还原后的图. 首先对行列建边, 源点向行 ...
- DjangoORM一对多&多对多操作
简要说明 通过操作对象的方式操作数据库 详细步骤 models.py的结构是: 如果models.py中外键定义没有写 related_name='student_teacher', 可以直接用 st ...
- java中的四则运算
代码的思路是通过正则判断计算每个最小的计算单元.以下是代码: package cn.com.lawchat.forpublicmvc.util; import java.math.BigDecimal ...
- “-Xmx1024m -Xms1024m -Xmn512m -Xss256k”——Java运行参数(转)
JVM的堆的内存, 是通过下面面两个参数控制的 -Xms 最小堆的大小, 也就是当你的虚拟机启动后, 就会分配这么大的堆内存给你 -Xmx 是最大堆的大小 当最小堆占满后,会尝试进行GC,如果GC之后 ...
- QT小记之在VS2005中使用(设置QMAKESPEC环境变量,以及编译QT Lib)
QT的结构很清晰明了,看过第一个HELLO WORLD便爱上了它,感觉CEGUI有借鉴过QT的设计.如何在Windows平台下使用QT开发?一,下载SDK包请去官网(QT被NOKIA收购,貌似使用协议 ...
- Make Yahoo! Web Service REST Calls With C#
原文 http://developer.yahoo.com/dotnet/howto-rest_cs.html The .NET Framework provides classes for perf ...