dll 与 exe 之间的通讯方式有很多种, 本文采用回调函数的方法实现, 本文也将研究多线程,多模块的情况下,回调函数所在的线程, 啥也不说了,先附上代码:

下面的是dll模块的的, dll的工程文件:

  1. library DllAPP;
  2. uses
  3. windows,
  4. SysUtils,
  5. Classes,
  6. DllClass in 'DllClass.pas';
  7. {$R *.res}
  8. var
  9. GDllServer: TDllServer;
  10. function AddServer(ADispatchFunc: TDispatchFunc): HRESULT; stdcall;
  11. begin
  12. Result := ERROR_INVALID_FUNCTION;
  13. if not Assigned(GDllServer) then
  14. Exit;
  15. GDllServer.AddServer(ADispatchFunc);
  16. Result := ERROR_SUCCESS;
  17. end;
  18. function DataDispatch(ACommand: Integer):HRESULT; stdcall;
  19. begin
  20. Result := ERROR_INVALID_FUNCTION;
  21. GDllServer.DataDispatch(ACommand);
  22. Result := 0;
  23. end;
  24. function DLLInitialize: HRESULT;
  25. begin
  26. Result := 1;
  27. GDllServer := TDllServer.create;
  28. Result := ERROR_SUCCESS;
  29. end;
  30. function  DllFinalize: HRESULT;
  31. begin
  32. Result := ERROR_INVALID_FUNCTION;
  33. GDllServer.Free;
  34. GDllServer := nil;
  35. Result := ERROR_SUCCESS;
  36. end;
  37. exports
  38. AddServer,
  39. DataDispatch,
  40. DLLInitialize,
  41. DllFinalize;
  42. begin
  43. end.

dll中的类型文件

  1. unit DllClass;
  2. interface
  3. uses
  4. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  5. Dialogs, StdCtrls;
  6. type
  7. TDispatchFunc = function(ACommand: Integer): HRESULT;stdcall;
  8. type
  9. TDLLSERVER = CLAss;
  10. TDLLThread = class(TThread)
  11. private
  12. FCount: Integer;
  13. FDllServer: TDllServer;
  14. public
  15. procedure Execute; override;
  16. public
  17. constructor create;
  18. end;
  19. TDllServer = class
  20. private
  21. FDispatchFunc: TDispatchFunc;
  22. FDllThread: TDLLThread;
  23. public
  24. procedure AddServer(ADispatchFunc: TDispatchFunc);
  25. procedure DataDispatch(ACommand: Integer);
  26. public
  27. constructor Create;
  28. destructor Destroy;
  29. end;
  30. implementation
  31. { TDllServer }
  32. ///保存exe的回调函数指针
  33. procedure TDllServer.AddServer(ADispatchFunc: TDispatchFunc);
  34. begin
  35. FDispatchFunc := ADispatchFunc;
  36. end;
  37. constructor TDllServer.create;
  38. var
  39. LThreadID: Cardinal;
  40. begin
  41. ///
  42. LThreadID := GetCurrentThreadid;
  43. ShowMessage('DLL,create:'+IntToStr(LThreadID));
  44. FDllThread := TDLLThread.create;
  45. FDllThread.FDllServer := Self;
  46. FDllThread.Resume;
  47. end;
  48. ///DLL接受exe传过来的指令, dll留给exe的调用借口
  49. procedure TDllServer.DataDispatch(ACommand: Integer);
  50. var
  51. LThreadID: Cardinal;
  52. begin
  53. if not Assigned(FDispatchFunc) then
  54. Exit;
  55. FDispatchFunc(ACommand);
  56. LThreadID := GetCurrentThreadid;
  57. ShowMessage('DLL,DateDispatch:'+IntToStr(LThreadID));
  58. end;
  59. destructor TDllServer.Destroy;
  60. begin
  61. ////
  62. end;
  63. { TDLLThread }
  64. constructor TDLLThread.create;
  65. var
  66. LThreadID: Cardinal;
  67. begin
  68. FCount := 0;
  69. inherited create(True);
  70. end;
  71. //这个函数的目的就是检验不同模块下的不同线程下,回调函数的执行线程
  72. procedure TDLLThread.Execute;
  73. var
  74. LThreadID: Cardinal;
  75. begin
  76. inherited;
  77. while not Terminated do
  78. begin
  79. Inc(FCount);
  80. if FCount = 2  then
  81. begin
  82. LThreadID := GetCurrentThreadid;
  83. ShowMessage('DLL,Thread--'+IntToStr(LThreadID));
  84. end;
  85. if FCount = 5 then
  86. begin
  87. if assigned(FDllServer) then
  88. begin
  89. FDllServer.FDispatchFunc(2);
  90. end;
  91. end;
  92. Sleep(1000);
  93. end;
  94. end;
  95. end.

exe的文件

  1. unit ExeClass;
  2. interface
  3. uses
  4. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  5. Dialogs, StdCtrls;
  6. type
  7. TDispatchFunc = function (ACommand: Integer): HRESULT;stdcall;
  8. TServerFunc = function (ADispatchFunc: TDispatchFunc): HRESULT;stdcall;
  9. TProc = function: HRESULT;
  10. type
  11. TForm2 = class(TForm)
  12. Button1: TButton;
  13. Memo1: TMemo;
  14. procedure FormDestroy(Sender: TObject);
  15. procedure Button1Click(Sender: TObject);
  16. procedure FormCreate(Sender: TObject);
  17. private
  18. { Private declarations }
  19. FServerDispatch: TServerFunc;    ///exe--->dll
  20. FDataDispatch: TDispatchFunc;    ///EXE--->DLL
  21. FDllInitialize: TProc;
  22. FDllFinalize: TProc;
  23. public
  24. { Public declarations }
  25. end;
  26. var
  27. Form2: TForm2;
  28. GHandleLibrary: THandle;
  29. GCount: Integer;
  30. implementation
  31. {$R *.dfm}
  32. ///DLL--->EXE,留给dll调用的回调函数
  33. function DataDispatch(ACommand: Integer): HRESULT; stdcall;
  34. var
  35. LThreadID: Cardinal;
  36. begin
  37. LThreadID := GetCurrentThreadid;
  38. ShowMessage('EXE:'+IntToStr(LThreadID));
  39. end;
  40. procedure TForm2.Button1Click(Sender: TObject);
  41. begin
  42. Inc(GCount);
  43. FDataDispatch(GCount);
  44. end;
  45. procedure TForm2.FormDestroy(Sender: TObject);
  46. begin
  47. FDllFinalize;
  48. FServerDispatch := nil;
  49. FDataDispatch := nil;
  50. FDllInitialize := nil;
  51. FDllFinalize := nil;
  52. FreeLibrary(GHandleLibrary);
  53. end;
  54. procedure TForm2.FormCreate(Sender: TObject);
  55. var
  56. LThreadID: Cardinal;
  57. begin
  58. GHandleLibrary := LoadLibrary(PChar('DLLAPP.dll'));
  59. @FDllInitialize := GetProcAddress(GHandleLibrary, 'DLLInitialize');
  60. @FDllFinalize := GetProcAddress(GHandleLibrary, 'DllFinalize');
  61. @FServerDispatch := GetProcAddress(GHandleLibrary, 'AddServer');
  62. @FDataDispatch := GetProcAddress(GHandleLibrary,'DataDispatch');
  63. FDllInitialize;
  64. FServerDispatch(DataDispatch);
  65. LThreadID := GetCurrentThreadid;
  66. Memo1.Lines.Add(IntToStr(LThreadID));
  67. end;
  68. 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之间的通讯调用 以及 回调函数的线程执行空间的更多相关文章

  1. Python并发编程06 /阻塞、异步调用/同步调用、异步回调函数、线程queue、事件event、协程

    Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件event.协程 目录 Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件 ...

  2. [Effective JavaScript 笔记]第67条:绝不要同步地调用异步的回调函数

    设想有downloadAsync函数的一种变种,它持有一个缓存(实现为一个Dict)来避免多次下载同一个文件.在文件已经被缓存的情况下,立即调用回调函数是最优选择. var cache=new Dic ...

  3. setInterval调用ajax回调函数不执行的问题

    setInterval调用ajax回调函数不执行 1.首先检查你的setInterval()函数写法是否正确 参考写法 // 检查是否支付成功 var isPayRequest=false; var ...

  4. frameset,iframe框架之间如何互相调用变量、函数

    以往一直在编写的都是前台的UI,很少使用到frameset.iframe,对其了解也是十分有限,只是知道其可以为其当前页面引入html文件成为当前页的一部分,但是这两天在做后台UI界面的时候,发现这样 ...

  5. C#调用C++回调函数的问题

    C++的回调函数中有一个参数是,是返回一个字符串,原则如下: typedef   void   (*TDataEvent)(char   *AData   ,int   ALen); 其中char   ...

  6. (转载)spring 之间的远程调用-Spring Http调用的实现

    原文:https://www.cnblogs.com/lewisat/p/6132082.html 1:Spring Http设计思想 最近在研究公司自己的一套rpc远程调用框架,看到其内部实现的设计 ...

  7. python 调用dll 动态链接库 结构体参数及回调函数等示例

    结构体示例: 这里是 C 代码的部分,主要是结构体的声明和回调函数定义. // 新版本定义 typedef enum { DevCard, DevLocator, DevReader } DevTyp ...

  8. python处理多线程之间事件通讯方法

    一.什么是事件 每执行一个事情,肯定有该事情的执行后状态,那事件就是该事情发生的信号 在程序中,多线程之间需要通讯,而事件就是方便线程之间的通讯 案例: 1.服务器启动需要5秒 2.客服端启动后去链接 ...

  9. Silverlight中异步调用WCF服务,传入回调函数

    以前学的ASP.NET,调用的都是同步方法,同步方法的好处就是,一步一步走,完成这步才会走下一步.然而,WCF使用的都是异步方法,调用之后不管有没有获得结果就直接往下走,最可恶的是异步函数都是Void ...

随机推荐

  1. 简单的Session登录

    Login前台页面 <form id="form1" action ="" method="post"> <input t ...

  2. 前端新人学习笔记-------html/css/js基础知识点(二)

    4月7日学到的知识点:     一:<img src="1.png" alt="美女"/> alt是给图片添加介绍,当图片没加载出来时,会直接显示a ...

  3. 关于ECMAScript6一些知识

    ECMAScript 是当前 JavaScript 语言规范的最新标准,一般称为 es6, 但是因为 该标准规范是在 2015年6月份发布的,所以也叫作 ECMAScript 2015 let 变量声 ...

  4. Ghost Button制作教程及设计趋势分析

    概述:Ghost Button(虚拟按钮)是网页设计中一个非常实用的按钮样式,特别是图片背景中,有出色的效果.今天我们一起来研究Ghost Button的各种效果的制作方法,并对Ghost Butto ...

  5. android SDK和ADT的更新

    ADT版本较低时,造成xml布局文件无法预览,更新时发现google被墙,找网上的招数暂且解决了问题. 1. SDK的更新: 将https://修改为http:// 修改方法是:在Android SD ...

  6. BZOJ 3533: [Sdoi2014]向量集( 线段树 + 三分 )

    答案一定是在凸壳上的(y>0上凸壳, y<0下凸壳). 线段树维护, 至多N次询问, 每次询问影响O(logN)数量级的线段树结点, 每个结点O(logN)暴力建凸壳, 然后O(logN) ...

  7. MySql按指定天数进行分组数据统计分析 2

    上次的随笔1中写的分组方式,经分析,是从前往后进行分组,即若选择2014的数据进行统计每11天为一组的话,1的分组方式, 按照2014-01-01——2014-01-11为一组,之后每11天为一组. ...

  8. Java中的流程控制(三)

    关于Java中的流程控制 关于Java中的流程控制 4.do while语句 do while语句的功能和while语句差不多,只不过它是在执行完第一次循环后才检测条件表达式的值,这意味着包含在大括号 ...

  9. 一个原生js写的加减乘除运算

    根据我的经验我说的再多也没人看,不过还是简单介绍下效果吧,可以选择+,-,*,/,去计算数据,喜欢的话就粘贴复制自己看去吧! <!DOCTYPE html PUBLIC "-//W3C ...

  10. Delphi 2010下载+完美破解

    点击链接进入http://altd.embarcadero.com/download/RADStudio2010/delphicbuilder_2010_3615_win.isoRAD Studio/ ...