D语言创建和调用DLL学习笔记

测试环境:win10 64bit+dmd2.103.0+vs community 2015(cl.exe即vc链接)。

一、创建dll的步骤

  1. 创建dllmain.d
  1 import core.sys.windows.windows;
  2 import core.sys.windows.dll;
  3 
  4 __gshared HINSTANCE g_hInst;
  5 
  6 extern (Windows)
  7 BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
  8 {
  9     switch (ulReason)
 10     {
 11 	case DLL_PROCESS_ATTACH:
 12 	    g_hInst = hInstance;
 13 	    dll_process_attach( hInstance, true );
 14 	    break;
 15 
 16 	case DLL_PROCESS_DETACH:
 17 	    dll_process_detach( hInstance, true );
 18 	    break;
 19 
 20 	case DLL_THREAD_ATTACH:
 21 	    dll_thread_attach( true, true );
 22 	    break;
 23 
 24 	case DLL_THREAD_DETACH:
 25 	    dll_thread_detach( true, true );
 26 	    break;
 27 	default:break;
 28     }
 29 
 30     return true;
 31 }
 32 

  2. 创建导出函数模块mydll.d

  1 module mydll;
  2 import core.stdc.stdio;
  3 
  4 export void dllprint()
  5 {
  6   printf("hello dll world\n");
  7 }
  8 

  3. 创建模块定义文件mydll.def

  1 LIBRARY "mydll.dll"
  2 EXETYPE NT
  3 SUBSYSTEM WINDOWS
  4 CODE SHARED EXECUTE
  5 DATA WRITE

  4. 编译生成mydll.lib和mydll.dll的批处理文件build_dll.bat。-m64指示编译器和连接器生成64位静态库和动态库。

  1 rem set PATH=c:\person\dmd2\windows\bin;c:\person\dmd2\windows\lib;%PATH%
  2 dmd -m64 -ofmydll.dll  mydll.d dllmain.d mydll.def
  3 pause

  查看目录文件夹确保mydll.lib和mydll.dll已生成

1.5

5. 创建子目录\test,在其内创建导出函数接口文件(类同c的头文件,只有函数声明,没有实现)模块mydll.di,将模块mydll.d里的实现部分剥离

  1 /module mydll;
  2 
  3 export void dllprint();
  4 

  6. 在子目录\test下创建测试主程序模块test.d,程序运行时动态链接mydll.di

  1 module test;
  2 
  3 import mydll;
  4 import std.stdio;
  5 int main()
  6 {
  7 	mydll.dllprint();
  8 
  9 	readln;
 10 	return 0;
 11 }

  7. 编译测试程序批处理文件buid_test.bat,注意不需要mydll.d即包含函数实现的这个模块文件,这也是库(lib/dll)的目的和作用所在。-m64 指示生成64位应用程序。

  1 rem set PATH=c:\person\dmd2\windows\bin;c:\person\dmd2\windows\lib;%PATH%
  2 dmd -m64 test.d mydll.lib
  3 pause

  8. 查看目录内test.exe已生成,再次留意这里必要的文件是test.d ,mydll.lib,mydll.dll,和头文件mydll.di,没有mydll.d

1.6

  9. 运行test.exe

1.7

二、代码内调用dll

  1. 创建class_from_dll.d,这次将导出函数模块放在一起。另外除了自由函数动态库的生成,也测试类方法(class method)动态库的生成与调用。
  1 module class_from_dll;
  2 
  3 import core.sys.windows.windows;
  4 import core.sys.windows.dll;
  5 
  6 
  7 __gshared HINSTANCE g_hInst;
  8 
  9 version(Windows)
 10 {
 11 
 12     //mixin SimpleDLLMain;
 13     extern (Windows)
 14     BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
 15     {
 16         switch (ulReason)
 17         {
 18         case DLL_PROCESS_ATTACH:
 19             g_hInst = hInstance;
 20             dll_process_attach( hInstance, true );
 21             break;
 22 
 23         case DLL_PROCESS_DETACH:
 24             dll_process_detach( hInstance, true );
 25             break;
 26 
 27         case DLL_THREAD_ATTACH:
 28             dll_thread_attach( true, true );
 29             break;
 30 
 31         case DLL_THREAD_DETACH:
 32             dll_thread_detach( true, true );
 33             break;
 34         default:break;
 35         }
 36 
 37         return true;
 38     }
 39 }
 40 
 41 extern(C):
 42     export void showMessage()
 43     {
 44         //printf is ok of course
 45         //import core.stdc.stdio;
 46         //printf("Hello from exported function showMessage().\n");
 47 
 48         import std.stdio;
 49         writeln("Hello from exported function showMessage().");
 50     }
 51 
 52 
 53     export class ClassFromDLL
 54     {
 55         void print()
 56         {
 57             //printf ok;
 58             //import core.stdc.stdio;
 59             //printf("Hello from exported Class.print().\n");
 60 
 61             import std.stdio;
 62             writeln("Hello from exported Class.print().");
 63         }
 64     }
 65     export ClassFromDLL factory(){return new ClassFromDLL;}

  2. 创建导出函数头文件模块class_from_dll.di

  1 module class_from_dll;
  2 
  3 extern(C):
  4 extern void showMessage();
  5 extern class ClassFromDLL
  6 {
  7     void print();
  8 }
  9 extern ClassFromDLL factory();

  3. 创建测试主程序模块app.d,代码内调用dll

  1 module app;
  2 
  3 import std.stdio;
  4 import core.runtime;
  5 import core.sys.windows.windows;
  6 import core.sys.windows.winbase:GetProcAddress;
  7 
  8 import class_from_dll;//  .di
  9 
 10 void print_from_main()
 11 {
 12     writeln("Hello from main function print_from_main().");
 13 }
 14 
 15 void main()
 16 {
 17     //dmd 2.04x的时候需要call Runtime.initialize()和Runtime.unloadLibrary(lib);
 18     //Runtime.initialize();
 19     void* lib = Runtime.loadLibrary("class_from_dll.dll");
 20 
 21     auto print=cast(void function())GetProcAddress(lib,"showMessage");
 22 
 23     print();
 24 
 25 
 26     auto factoryFunction = cast(typeof(&factory))GetProcAddress(lib, factory.mangleof);
 27     ClassFromDLL cls = factoryFunction();
 28     cls.print();
 29 
 30     //Runtime.unloadLibrary(lib);
 31 
 32     print_from_main();
 33 
 34     writeln("\nDone.\nPress any key to exit...");
 35 
 36     readln;
 37 }

  4. 一切就绪,这次将创建库(lib/dll)和测试主程序的编译放在一个批处理文件里buildAll.bat一键完成。-m64指示生成64位静态库、动态库和最终的测试应用程序。

注意这次生成主程序时不需用静态库class_from_dll.lib

  1 rem set PATH=c:\person\dmd2\windows\bin;c:\person\dmd2\windows\lib;%PATH%
  2 dmd -m64 -shared class_from_dll.d
  3 dmd  -m64 app.d class_from_dll.di
  4 pause

  5. 查看目录内class_from_dll.lib,class_from_dll.dll,以及app.exe应已生成。

2.5

  6. 运行app.exe

2.6

posted @ 2023-04-25 15:38  高斯山  阅读(93)  评论(0编辑  收藏  举报