moduleloader.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. unit moduleloader;
  2. {
  3. $Id: moduleloader.pas,v 1.4 2004/02/20 17:19:10 savage Exp $
  4. }
  5. {******************************************************************}
  6. { }
  7. { Project JEDI }
  8. { OS independent Dynamic Loading Helpers }
  9. { }
  10. { The initial developer of the this code is }
  11. { Robert Marquardt <[email protected]) }
  12. { }
  13. { Copyright (C) 2000, 2001 Robert Marquardt. }
  14. { }
  15. { Obtained through: }
  16. { Joint Endeavour of Delphi Innovators (Project JEDI) }
  17. { }
  18. { You may retrieve the latest version of this file at the Project }
  19. { JEDI home page, located at http://delphi-jedi.org }
  20. { }
  21. { The contents of this file are used with permission, subject to }
  22. { the Mozilla Public License Version 1.1 (the "License"); you may }
  23. { not use this file except in compliance with the License. You may }
  24. { obtain a copy of the License at }
  25. { http://www.mozilla.org/NPL/NPL-1_1Final.html }
  26. { }
  27. { Software distributed under the License is distributed on an }
  28. { "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
  29. { implied. See the License for the specific language governing }
  30. { rights and limitations under the License. }
  31. { }
  32. {******************************************************************}
  33. {
  34. $Log: moduleloader.pas,v $
  35. Revision 1.4 2004/02/20 17:19:10 savage
  36. Added Calling convention to Win32 functions just in case.
  37. Revision 1.3 2004/02/14 22:36:29 savage
  38. Fixed inconsistencies of using LoadLibrary and LoadModule.
  39. Now all units make use of LoadModule rather than LoadLibrary and other dynamic proc procedures.
  40. Revision 1.2 2004/02/14 00:23:39 savage
  41. As UNIX is defined in jedi-sdl.inc this will be used to check linux compatability as well. Units have been changed to reflect this change.
  42. Revision 1.1 2004/02/14 00:04:50 savage
  43. dllfuncs conflicts with FreePascal so it has been renamed back to the moduleloader.pas
  44. Revision 1.1 2004/02/05 00:08:19 savage
  45. Module 1.0 release
  46. }
  47. interface
  48. {$i jedi-sdl.inc}
  49. {$WEAKPACKAGEUNIT ON}
  50. // each OS gets its own IFDEFed complete code block to make reading easier
  51. {$IFDEF WIN32}
  52. uses
  53. Windows;
  54. type
  55. // Handle to a loaded DLL
  56. TModuleHandle = HINST;
  57. const
  58. // Value designating an unassigned TModuleHandle od a failed loading
  59. INVALID_MODULEHANDLE_VALUE = TModuleHandle(0);
  60. function LoadModule(var Module: TModuleHandle; FileName: PChar): Boolean; stdcall;
  61. function LoadModuleEx(var Module: TModuleHandle; FileName: PChar; Flags: Cardinal): Boolean; stdcall;
  62. procedure UnloadModule(var Module: TModuleHandle); stdcall;
  63. function GetModuleSymbol(Module: TModuleHandle; SymbolName: PChar): Pointer; stdcall;
  64. function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: PChar; var Accu: Boolean): Pointer; stdcall;
  65. function ReadModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean; stdcall;
  66. function WriteModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean; stdcall;
  67. implementation
  68. // load the DLL file FileName
  69. // the rules for FileName are those of LoadLibrary
  70. // Returns: True = success, False = failure to load
  71. // Assigns: the handle of the loaded DLL to Module
  72. // Warning: if Module has any other value than INVALID_MODULEHANDLE_VALUE
  73. // on entry the function will do nothing but returning success.
  74. function LoadModule(var Module: TModuleHandle; FileName: PChar): Boolean;
  75. begin
  76. if Module = INVALID_MODULEHANDLE_VALUE then
  77. Module := LoadLibrary( FileName );
  78. Result := Module <> INVALID_MODULEHANDLE_VALUE;
  79. end;
  80. // load the DLL file FileName
  81. // LoadLibraryEx is used to get better control of the loading
  82. // for the allowed values for flags see LoadLibraryEx documentation.
  83. function LoadModuleEx(var Module: TModuleHandle; FileName: PChar; Flags: Cardinal): Boolean;
  84. begin
  85. if Module = INVALID_MODULEHANDLE_VALUE then
  86. Module := LoadLibraryEx( FileName, 0, Flags);
  87. Result := Module <> INVALID_MODULEHANDLE_VALUE;
  88. end;
  89. // unload a DLL loaded with LoadModule or LoadModuleEx
  90. // The procedure will not try to unload a handle with
  91. // value INVALID_MODULEHANDLE_VALUE and assigns this value
  92. // to Module after unload.
  93. procedure UnloadModule(var Module: TModuleHandle);
  94. begin
  95. if Module <> INVALID_MODULEHANDLE_VALUE then
  96. FreeLibrary(Module);
  97. Module := INVALID_MODULEHANDLE_VALUE;
  98. end;
  99. // returns the pointer to the symbol named SymbolName
  100. // if it is exported from the DLL Module
  101. // nil is returned if the symbol is not available
  102. function GetModuleSymbol(Module: TModuleHandle; SymbolName: PChar): Pointer;
  103. begin
  104. Result := nil;
  105. if Module <> INVALID_MODULEHANDLE_VALUE then
  106. Result := GetProcAddress(Module, SymbolName );
  107. end;
  108. // returns the pointer to the symbol named SymbolName
  109. // if it is exported from the DLL Module
  110. // nil is returned if the symbol is not available.
  111. // as an extra the boolean variable Accu is updated
  112. // by anding in the success of the function.
  113. // This is very handy for rendering a global result
  114. // when accessing a long list of symbols.
  115. function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: PChar; var Accu: Boolean): Pointer;
  116. begin
  117. Result := nil;
  118. if Module <> INVALID_MODULEHANDLE_VALUE then
  119. Result := GetProcAddress(Module, SymbolName );
  120. Accu := Accu and (Result <> nil);
  121. end;
  122. // get the value of variables exported from a DLL Module
  123. // Delphi cannot access variables in a DLL directly, so
  124. // this function allows to copy the data from the DLL.
  125. // Beware! You are accessing the DLL memory image directly.
  126. // Be sure to access a variable not a function and be sure
  127. // to read the correct amount of data.
  128. function ReadModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
  129. var
  130. Sym: Pointer;
  131. begin
  132. Result := True;
  133. Sym := GetModuleSymbolEx(Module, SymbolName, Result);
  134. if Result then
  135. Move(Sym^, Buffer, Size);
  136. end;
  137. // set the value of variables exported from a DLL Module
  138. // Delphi cannot access variables in a DLL directly, so
  139. // this function allows to copy the data to the DLL!
  140. // BEWARE! You are accessing the DLL memory image directly.
  141. // Be sure to access a variable not a function and be sure
  142. // to write the correct amount of data.
  143. // The changes are not persistent. They get lost when the
  144. // DLL is unloaded.
  145. function WriteModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
  146. var
  147. Sym: Pointer;
  148. begin
  149. Result := True;
  150. Sym := GetModuleSymbolEx(Module, SymbolName, Result);
  151. if Result then
  152. Move(Buffer, Sym^, Size);
  153. end;
  154. {$ENDIF}
  155. {$IFDEF Unix}
  156. uses
  157. {$ifdef Linux}
  158. Types,
  159. Libc;
  160. {$else}
  161. dl,
  162. Types,
  163. Baseunix,
  164. Unix;
  165. {$endif}
  166. type
  167. // Handle to a loaded .so
  168. TModuleHandle = Pointer;
  169. const
  170. // Value designating an unassigned TModuleHandle od a failed loading
  171. INVALID_MODULEHANDLE_VALUE = TModuleHandle(nil);
  172. function LoadModule(var Module: TModuleHandle; FileName: PChar): Boolean;
  173. function LoadModuleEx(var Module: TModuleHandle; FileName: PChar; Flags: Cardinal): Boolean;
  174. procedure UnloadModule(var Module: TModuleHandle);
  175. function GetModuleSymbol(Module: TModuleHandle; SymbolName: PChar): Pointer;
  176. function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: PChar; var Accu: Boolean): Pointer;
  177. function ReadModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
  178. function WriteModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
  179. implementation
  180. // load the .so file FileName
  181. // the rules for FileName are those of dlopen()
  182. // Returns: True = success, False = failure to load
  183. // Assigns: the handle of the loaded .so to Module
  184. // Warning: if Module has any other value than INVALID_MODULEHANDLE_VALUE
  185. // on entry the function will do nothing but returning success.
  186. function LoadModule(var Module: TModuleHandle; FileName: PChar): Boolean;
  187. begin
  188. if Module = INVALID_MODULEHANDLE_VALUE then
  189. Module := dlopen( FileName, RTLD_NOW);
  190. Result := Module <> INVALID_MODULEHANDLE_VALUE;
  191. end;
  192. // load the .so file FileName
  193. // dlopen() with flags is used to get better control of the loading
  194. // for the allowed values for flags see "man dlopen".
  195. function LoadModuleEx(var Module: TModuleHandle; FileName: PChar; Flags: Cardinal): Boolean;
  196. begin
  197. if Module = INVALID_MODULEHANDLE_VALUE then
  198. Module := dlopen( FileName, Flags);
  199. Result := Module <> INVALID_MODULEHANDLE_VALUE;
  200. end;
  201. // unload a .so loaded with LoadModule or LoadModuleEx
  202. // The procedure will not try to unload a handle with
  203. // value INVALID_MODULEHANDLE_VALUE and assigns this value
  204. // to Module after unload.
  205. procedure UnloadModule(var Module: TModuleHandle);
  206. begin
  207. if Module <> INVALID_MODULEHANDLE_VALUE then
  208. dlclose(Module);
  209. Module := INVALID_MODULEHANDLE_VALUE;
  210. end;
  211. // returns the pointer to the symbol named SymbolName
  212. // if it is exported from the .so Module
  213. // nil is returned if the symbol is not available
  214. function GetModuleSymbol(Module: TModuleHandle; SymbolName: PChar): Pointer;
  215. begin
  216. Result := nil;
  217. if Module <> INVALID_MODULEHANDLE_VALUE then
  218. Result := dlsym(Module, SymbolName );
  219. end;
  220. // returns the pointer to the symbol named SymbolName
  221. // if it is exported from the .so Module
  222. // nil is returned if the symbol is not available.
  223. // as an extra the boolean variable Accu is updated
  224. // by anding in the success of the function.
  225. // This is very handy for rendering a global result
  226. // when accessing a long list of symbols.
  227. function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: PChar; var Accu: Boolean): Pointer;
  228. begin
  229. Result := nil;
  230. if Module <> INVALID_MODULEHANDLE_VALUE then
  231. Result := dlsym(Module, SymbolName );
  232. Accu := Accu and (Result <> nil);
  233. end;
  234. // get the value of variables exported from a .so Module
  235. // Delphi cannot access variables in a .so directly, so
  236. // this function allows to copy the data from the .so.
  237. // Beware! You are accessing the .so memory image directly.
  238. // Be sure to access a variable not a function and be sure
  239. // to read the correct amount of data.
  240. function ReadModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
  241. var
  242. Sym: Pointer;
  243. begin
  244. Result := True;
  245. Sym := GetModuleSymbolEx(Module, SymbolName, Result);
  246. if Result then
  247. Move(Sym^, Buffer, Size);
  248. end;
  249. // set the value of variables exported from a .so Module
  250. // Delphi cannot access variables in a .so directly, so
  251. // this function allows to copy the data to the .so!
  252. // BEWARE! You are accessing the .so memory image directly.
  253. // Be sure to access a variable not a function and be sure
  254. // to write the correct amount of data.
  255. // The changes are not persistent. They get lost when the
  256. // .so is unloaded.
  257. function WriteModuleData(Module: TModuleHandle; SymbolName: PChar; var Buffer; Size: Cardinal): Boolean;
  258. var
  259. Sym: Pointer;
  260. begin
  261. Result := True;
  262. Sym := GetModuleSymbolEx(Module, SymbolName, Result);
  263. if Result then
  264. Move(Buffer, Sym^, Size);
  265. end;
  266. {$ENDIF}
  267. {$IFDEF __MACH__} // Mach definitions go here
  268. {$ENDIF}
  269. end.