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. spring mvc 的基本注解

    刚开始学习spring mvc 有很多东西不是很了解 spring mvc 四个基本注解 annotation(控制层,业务层,持久层) -- @Component.@Repository   @Se ...

  2. 数据库分页【Limt与Limt..OFFSET 】

    数据起始 SELECT * from xiaoyao_blogs_essay  limit 20 , 15;解释:20是起始位置,15是页容量.因为id是从15开始的 SELECT * from xi ...

  3. mongodb数据库调试问题:‘db object already connecting, open cannot be called multiple times’

    在微博小系统的调试过程中: (1)登入登出可以正常显示,就是在注册的时候网络连接突然停止,但是用户名和密码已经存入数据库中,报错为:undefined is not a function 错误主要指向 ...

  4. poj 3270 置换

    poj 置换的应用 黑书原题P248 /** 题意: 给定序列, 将其按升序排列, 每次交换的代价是两个数之和, 问代价最小是多少 思路:1.对于同一个循环节之内的,肯定是最小的与别的交换代价最小 2 ...

  5. 在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be closed first”

    在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be ...

  6. Minix

    [1]  MINIX是一种基于微内核架构的类UNIX计算机操作系统,由Andrew S. Tanenbaum发明.MINIX最初发布于1987年,开放全部源代码给大学教学和研究工作.2000年重新改为 ...

  7. Spring jdbctemplate学习笔记

    /*List<?> config = getDB(" select t.datavalue from sys_config t where t.configid = '15' & ...

  8. 再探Delphi2010 Class的构造和析构顺序

    发了上一篇博客.盒子上有朋友认为Class的构造和析构延迟加载.是在Unit的初始化后调用的Class的构造.在Unit的反初始化前调用的Class的析构函数. 为了证明一下我又做了个试验 unit ...

  9. 将 SQL Server 实例设置为自动启动(SQL Server 配置管理器)

    本主题说明如何使用 SQL Server 配置管理器在 SQL Server 2012 中将 SQL Server 实例设置为自动启动. 在安装过程中,SQL Server 通常配置为自动启动. 如果 ...

  10. sicily-1029 Rabbit

    一.      题意(0.04s) 每一对成熟的兔子可以生一对兔子,兔子在m个月之后成熟,假设兔子都不会死,计算d个月后一共有多少只兔子. 二.      要高精度加法(用string) 三.     ...