C#-like 的 DLL 封装

一个类似 C# 的 DllImport 实现,用于“半”动态加载 DLL。用起来比我以前写的 DLLWrapper 要麻烦一些,但是 DLLWrapper 由于使用一个 Tuple 来存储函数声明,会造成超长的标识符导致编译错误,这个 DllImport 避免了这个问题。

这个实现有一个缺陷是每次调用API函数的时候都会执行一次 GetProcAddress,效率比较低.... 谁能告诉我怎么避免该死的 CTFE?

代码
  1. // DllImport - A C#-like DLL Wrapper
  2. // written by oldrev (wstring#gmail.com)
  3. // License: BSD
  4. import std.stdio;
  5. import std.typetuple;
  6. import std.utf;
  7. import std.c.windows.windows;
  8. import std.traits;
  9. import std.string;
  10. import singleton;
  11. extern(Windows)
  12. {
  13. HMODULE LoadLibraryW(LPCWSTR libPath);
  14. }
  15. private static class ModuleManager
  16. {
  17. private static HMODULE [char[]] m_modules;
  18. private this()
  19. {
  20. }
  21. static public ~this()
  22. {
  23. foreach(h; m_modules)
  24. {
  25. FreeLibrary(h);
  26. }
  27. }
  28. private static HMODULE registerModule(char[] name)
  29. {
  30. char[] lname = tolower(name);
  31. HMODULE h = LoadLibraryW(toUTF16z(lname));
  32. if(h is null)
  33. throw new Exception("Failed to load DLL: " ~ name);
  34. m_modules[lname] = h;
  35. return h;
  36. }
  37. public static HMODULE getHandle(char[] name)
  38. {
  39. return m_modules[name];
  40. }
  41. public static ProcType getSymbol(ProcType)(char[] moduleName, char[] procName)
  42. {
  43. HMODULE handle = null;
  44. if(moduleName in m_modules)
  45. handle = m_modules[moduleName];
  46. else
  47. handle = registerModule(moduleName);
  48. assert(handle !is null);
  49. return cast(ProcType)GetProcAddress(handle, toStringz(procName));
  50. }
  51. }
  52. struct DllImport(char[] ModuleName, char[] ProcName, FT)
  53. {
  54. extern(Windows) alias ReturnType!(FT)
  55. function(ParameterTypeTuple!(FT)) FunctionType;
  56. // 非要这样重新绑定 extern(Windows),是不是编译器的 bug?
  57. // extern(Windows) alias FT FunctionType; // 这样就不行
  58. //怎么避免 CTFE?
  59. //FIXME:
  60. //FunctionType m_funcPtr = ModuleManager.getSymbol!(FunctionType)(ModuleName, ProcName);
  61. public ReturnType!(FunctionType) opCall(ParameterTypeTuple!(FunctionType) args)
  62. {
  63. FunctionType m_funcPtr = ModuleManager.getSymbol!(FunctionType)(ModuleName, ProcName);
  64. return m_funcPtr(args);
  65. }
  66. }
  67. void main()
  68. {
  69. DllImport!("user32.dll", "MessageBoxA",
  70. int function(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)) MessageBox;
  71. MessageBox(null, "Text", "Title", MB_OK);
  72. }

你可能感兴趣的:(C++,c,windows,C#,Gmail)