2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
12 #include "cores/DllLoader/LibraryLoader.h"
16 ///////////////////////////////////////////////////////////
18 // DECLARE_DLL_WRAPPER
20 // Declares the constructor of the wrapper class.
21 // This must be followed by one or more
22 // DEFINE_METHODX/DEFINE_METHOD_LINKAGEX and
23 // one BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE block.
25 // classname: name of the wrapper class to construct
26 // dllname: file including path of the dll to wrap
28 #define DECLARE_DLL_WRAPPER(classname, dllname) \
29 XDECLARE_DLL_WRAPPER(classname,dllname)
31 #define XDECLARE_DLL_WRAPPER(classname, dllname) \
33 classname () : DllDynamic( dllname ) {}
35 ///////////////////////////////////////////////////////////
37 // DECLARE_DLL_WRAPPER_TEMPLATE_BEGIN
39 // Declares the constructor of the wrapper class.
40 // The method SetFile(strDllName) can be used to set the
41 // dll of this wrapper.
42 // This must be followed by one or more
43 // DEFINE_METHODX/DEFINE_METHOD_LINKAGEX and
44 // one BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE block.
46 // classname: name of the wrapper class to construct
48 #define DECLARE_DLL_WRAPPER_TEMPLATE(classname) \
53 ///////////////////////////////////////////////////////////
57 // Tells the dllloader to load Debug symbols when possible
58 #define LOAD_SYMBOLS() \
60 virtual bool LoadSymbols() { return true; }
62 ///////////////////////////////////////////////////////////
66 // Defines a global for export from the dll as well as
67 // a function for accessing it (Get_name).
69 // type: The variables type.
70 // name: Name of the variable.
73 #define DEFINE_GLOBAL_PTR(type, name) \
77 void* m_##name##_ptr; \
80 virtual type* Get_##name (void) \
85 #define DEFINE_GLOBAL(type, name) \
89 void* m_##name##_ptr; \
92 virtual type Get_##name (void) \
97 ///////////////////////////////////////////////////////////
99 // DEFINE_METHOD_LINKAGE
101 // Defines a function for an export from a dll, if the
102 // calling convention is not __cdecl.
103 // Use DEFINE_METHOD_LINKAGE for each function to be resolved.
105 // result: Result of the function
106 // linkage: Calling convention of the function
107 // name: Name of the function
108 // args: Arguments of the function, enclosed in parentheses
110 #define DEFINE_METHOD_LINKAGE_FP(result, linkage, name, args) \
112 typedef result (linkage * name##_METHOD) args; \
115 name##_METHOD m_##name; \
116 void* m_##name##_ptr; \
119 #define DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, args2) \
121 typedef result (linkage * name##_METHOD) args; \
123 name##_METHOD m_##name; \
124 void* m_##name##_ptr; \
127 virtual result name args override \
129 return m_##name ? m_##name args2 : (result) 0; \
132 #define DEFINE_METHOD_LINKAGE0(result, linkage, name) \
133 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, () , ())
135 #define DEFINE_METHOD_LINKAGE1(result, linkage, name, args) \
136 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1))
138 #define DEFINE_METHOD_LINKAGE2(result, linkage, name, args) \
139 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2))
141 #define DEFINE_METHOD_LINKAGE3(result, linkage, name, args) \
142 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3))
144 #define DEFINE_METHOD_LINKAGE4(result, linkage, name, args) \
145 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4))
147 #define DEFINE_METHOD_LINKAGE5(result, linkage, name, args) \
148 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5))
150 #define DEFINE_METHOD_LINKAGE6(result, linkage, name, args) \
151 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6))
153 #define DEFINE_METHOD_LINKAGE7(result, linkage, name, args) \
154 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7))
156 #define DEFINE_METHOD_LINKAGE8(result, linkage, name, args) \
157 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8))
159 #define DEFINE_METHOD_LINKAGE9(result, linkage, name, args) \
160 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8, p9))
162 #define DEFINE_METHOD_LINKAGE10(result, linkage, name, args) \
163 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))
165 #define DEFINE_METHOD_LINKAGE11(result, linkage, name, args) \
166 DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11))
168 ///////////////////////////////////////////////////////////
172 // Defines a function for an export from a dll as a function pointer.
173 // Use DEFINE_METHOD_FP for each function to be resolved. Functions
174 // defined like this are not listed by IntelliSence.
176 // result: Result of the function
177 // name: Name of the function
178 // args: Arguments of the function, enclosed in parentheses
179 // The parameter names can be anything
181 #define DEFINE_METHOD_FP(result, name, args) DEFINE_METHOD_LINKAGE_FP(result, __cdecl, name, args)
183 ///////////////////////////////////////////////////////////
187 // Defines a function for an export from a dll.
188 // Use DEFINE_METHODX for each function to be resolved.
189 // where X is the number of parameter the function has.
191 // result: Result of the function
192 // name: Name of the function
193 // args: Arguments of the function, enclosed in parentheses
194 // The parameter names have to be renamed to px, where
195 // x is the number of the parameter
197 #define DEFINE_METHOD0(result, name) DEFINE_METHOD_LINKAGE0(result, __cdecl, name)
198 #define DEFINE_METHOD1(result, name, args) DEFINE_METHOD_LINKAGE1(result, __cdecl, name, args)
199 #define DEFINE_METHOD2(result, name, args) DEFINE_METHOD_LINKAGE2(result, __cdecl, name, args)
200 #define DEFINE_METHOD3(result, name, args) DEFINE_METHOD_LINKAGE3(result, __cdecl, name, args)
201 #define DEFINE_METHOD4(result, name, args) DEFINE_METHOD_LINKAGE4(result, __cdecl, name, args)
202 #define DEFINE_METHOD5(result, name, args) DEFINE_METHOD_LINKAGE5(result, __cdecl, name, args)
203 #define DEFINE_METHOD6(result, name, args) DEFINE_METHOD_LINKAGE6(result, __cdecl, name, args)
204 #define DEFINE_METHOD7(result, name, args) DEFINE_METHOD_LINKAGE7(result, __cdecl, name, args)
205 #define DEFINE_METHOD8(result, name, args) DEFINE_METHOD_LINKAGE8(result, __cdecl, name, args)
206 #define DEFINE_METHOD9(result, name, args) DEFINE_METHOD_LINKAGE9(result, __cdecl, name, args)
207 #define DEFINE_METHOD10(result, name, args) DEFINE_METHOD_LINKAGE10(result, __cdecl, name, args)
208 #define DEFINE_METHOD11(result, name, args) DEFINE_METHOD_LINKAGE11(result, __cdecl, name, args)
210 #ifdef TARGET_WINDOWS
211 ///////////////////////////////////////////////////////////
213 // DEFINE_FUNC_ALIGNED 0-X
215 // Defines a function for an export from a dll, which
216 // requires an aligned stack on function call
217 // Use DEFINE_FUNC_ALIGNED for each function to be resolved.
219 // result: Result of the function
220 // linkage: Calling convention of the function
221 // name: Name of the function
222 // args: Argument types of the function
224 // Actual function call will expand to something like this
225 // this will align the stack (esp) at the point of function
226 // entry as required by gcc compiled dlls, it is a bit obfuscated
227 // to allow for different sized variables
229 // int64_t test(int64_t p1, char p2, char p3)
231 // int o,s = ((sizeof(p1)+3)&~3)+((sizeof(p2)+3)&~3)+((sizeof(p3)+3)&~3);
232 // __asm mov [o],esp;
233 // __asm sub esp, [s];
234 // __asm and esp, ~15;
235 // __asm add esp, [s]
236 // m_test(p1, p2, p3); //return value will still be correct as long as we don't mess with it
237 // __asm mov esp,[o];
240 #define ALS(a) ((sizeof(a)+3)&~3)
241 #define DEFINE_FUNC_PART1(result, linkage, name, args) \
243 typedef result (linkage * name##_type)##args; \
245 name##_type m_##name; \
246 void* m_##name##_ptr; \
249 virtual result name##args
251 #define DEFINE_FUNC_PART2(size) \
261 #define DEFINE_FUNC_PART3(name,args) \
268 #define DEFINE_FUNC_ALIGNED0(result, linkage, name) \
269 DEFINE_FUNC_PART1(result, linkage, name, ()) \
270 DEFINE_FUNC_PART2(0) \
271 DEFINE_FUNC_PART3(name,())
273 #define DEFINE_FUNC_ALIGNED1(result, linkage, name, t1) \
274 DEFINE_FUNC_PART1(result, linkage, name, (t1 p1)) \
275 DEFINE_FUNC_PART2(ALS(p1)) \
276 DEFINE_FUNC_PART3(name,(p1))
278 #define DEFINE_FUNC_ALIGNED2(result, linkage, name, t1, t2) \
279 DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2)) \
280 DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)) \
281 DEFINE_FUNC_PART3(name,(p1, p2))
283 #define DEFINE_FUNC_ALIGNED3(result, linkage, name, t1, t2, t3) \
284 DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3)) \
285 DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)) \
286 DEFINE_FUNC_PART3(name,(p1, p2, p3))
288 #define DEFINE_FUNC_ALIGNED4(result, linkage, name, t1, t2, t3, t4) \
289 DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4)) \
290 DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)) \
291 DEFINE_FUNC_PART3(name,(p1, p2, p3, p4))
293 #define DEFINE_FUNC_ALIGNED5(result, linkage, name, t1, t2, t3, t4, t5) \
294 DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5)) \
295 DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)) \
296 DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5))
298 #define DEFINE_FUNC_ALIGNED6(result, linkage, name, t1, t2, t3, t4, t5, t6) \
299 DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6)) \
300 DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)) \
301 DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6))
303 #define DEFINE_FUNC_ALIGNED7(result, linkage, name, t1, t2, t3, t4, t5, t6, t7) \
304 DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7)) \
305 DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)+ALS(p7)) \
306 DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6, p7))
308 #define DEFINE_FUNC_ALIGNED8(result, linkage, name, t1, t2, t3, t4, t5, t6, t7, t8) \
309 DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8)) \
310 DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)+ALS(p7)+ALS(p8)) \
311 DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6, p7, p8))
313 #define DEFINE_FUNC_ALIGNED9(result, linkage, name, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
314 DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9)) \
315 DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)+ALS(p7)+ALS(p8)+ALS(p9)) \
316 DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6, p7, p8, p9))
320 #define DEFINE_FUNC_ALIGNED0(result, linkage, name) DEFINE_METHOD_LINKAGE0 (result, linkage, name)
321 #define DEFINE_FUNC_ALIGNED1(result, linkage, name, t1) DEFINE_METHOD_LINKAGE1 (result, linkage, name, (t1 p1) )
322 #define DEFINE_FUNC_ALIGNED2(result, linkage, name, t1, t2) DEFINE_METHOD_LINKAGE2 (result, linkage, name, (t1 p1, t2 p2) )
323 #define DEFINE_FUNC_ALIGNED3(result, linkage, name, t1, t2, t3) DEFINE_METHOD_LINKAGE3 (result, linkage, name, (t1 p1, t2 p2, t3 p3) )
324 #define DEFINE_FUNC_ALIGNED4(result, linkage, name, t1, t2, t3, t4) DEFINE_METHOD_LINKAGE4 (result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4) )
325 #define DEFINE_FUNC_ALIGNED5(result, linkage, name, t1, t2, t3, t4, t5) DEFINE_METHOD_LINKAGE5 (result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5) )
326 #define DEFINE_FUNC_ALIGNED6(result, linkage, name, t1, t2, t3, t4, t5, t6) DEFINE_METHOD_LINKAGE6 (result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6) )
327 #define DEFINE_FUNC_ALIGNED7(result, linkage, name, t1, t2, t3, t4, t5, t6, t7) DEFINE_METHOD_LINKAGE7 (result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7) )
328 #define DEFINE_FUNC_ALIGNED8(result, linkage, name, t1, t2, t3, t4, t5, t6, t7, t8) DEFINE_METHOD_LINKAGE8 (result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8) )
329 #define DEFINE_FUNC_ALIGNED9(result, linkage, name, t1, t2, t3, t4, t5, t6, t7, t8, t9) DEFINE_METHOD_LINKAGE9 (result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9) )
330 #define DEFINE_FUNC_ALIGNED10(result, linkage, name, t1, t2, t3, t4, t5, t6, t7, t8, t10) DEFINE_METHOD_LINKAGE10(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10) )
331 #define DEFINE_FUNC_ALIGNED11(result, linkage, name, t1, t2, t3, t4, t5, t6, t7, t8, t10, t11) DEFINE_METHOD_LINKAGE11(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11) )
335 ///////////////////////////////////////////////////////////
337 // BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE
339 // Defines a method that resolves the exported functions
340 // defined with DEFINE_METHOD or DEFINE_METHOD_LINKAGE.
341 // There must be a RESOLVE_METHOD or RESOLVE_METHOD_RENAME
342 // for each DEFINE_METHOD or DEFINE_METHOD_LINKAGE within this
343 // block. This block must be followed by an END_METHOD_RESOLVE.
345 #define BEGIN_METHOD_RESOLVE() \
347 virtual bool ResolveExports() override \
350 #define END_METHOD_RESOLVE() \
354 ///////////////////////////////////////////////////////////
358 // Resolves a method from a dll
360 // method: Name of the method defined with DEFINE_METHOD
361 // or DEFINE_METHOD_LINKAGE
363 #define RESOLVE_METHOD(method) \
364 if (!m_dll->ResolveExport( #method , & m_##method##_ptr )) \
367 #define RESOLVE_METHOD_FP(method) \
368 if (!m_dll->ResolveExport( #method , & m_##method##_ptr )) \
372 ///////////////////////////////////////////////////////////
374 // RESOLVE_METHOD_OPTIONAL
376 // Resolves a method from a dll. does not abort if the
379 // method: Name of the method defined with DEFINE_METHOD
380 // or DEFINE_METHOD_LINKAGE
383 #define RESOLVE_METHOD_OPTIONAL(method) \
384 m_##method##_ptr = nullptr; \
385 m_dll->ResolveExport( #method , & m_##method##_ptr, false );
387 #define RESOLVE_METHOD_OPTIONAL_FP(method) \
388 m_##method##_ptr = NULL; \
389 m_dll->ResolveExport( #method , & m_##method##_ptr, false );
393 ///////////////////////////////////////////////////////////
395 // RESOLVE_METHOD_RENAME
397 // Resolves a method from a dll
399 // dllmethod: Name of the function exported from the dll
400 // method: Name of the method defined with DEFINE_METHOD
401 // or DEFINE_METHOD_LINKAGE
403 #define RESOLVE_METHOD_RENAME(dllmethod, method) \
404 if (!m_dll->ResolveExport( #dllmethod , & m_##method##_ptr )) \
407 #define RESOLVE_METHOD_RENAME_OPTIONAL(dllmethod, method) \
408 m_##method##_ptr = nullptr; \
409 m_dll->ResolveExport( #dllmethod , & m_##method##_ptr, false );
411 #define RESOLVE_METHOD_RENAME_FP(dllmethod, method) \
412 if (!m_dll->ResolveExport( #dllmethod , & method##_ptr )) \
416 ////////////////////////////////////////////////////////////////////
418 // Example declaration of a dll wrapper class
420 // 1. Define a class with pure virtual functions with all functions
421 // exported from the dll. This is needed to use the IntelliSence
422 // feature of the Visual Studio Editor.
424 // class DllExampleInterface
427 // virtual void foo (unsigned int type, char* szTest)=0;
428 // virtual void bar (char* szTest, unsigned int type)=0;
431 // 2. Define a class, derived from DllDynamic and the previously defined
432 // interface class. Define the constructor of the class using the
433 // DECLARE_DLL_WRAPPER macro. Use the DEFINE_METHODX/DEFINE_METHOD_LINKAGEX
434 // macros to define the functions from the interface above, where X is number of
435 // parameters the function has. The function parameters
436 // have to be enclosed in parentheses. The parameter names have to be changed to px
437 // where x is the number on which position the parameter appears.
438 // Use the RESOLVE_METHOD/RESOLVE_METHOD_RENAME to do the actually resolve the functions
439 // from the dll when it's loaded. The RESOLVE_METHOD/RESOLVE_METHOD_RENAME have to
440 // be between the BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE block.
442 // class DllExample : public DllDynamic, DllExampleInterface
444 // DECLARE_DLL_WRAPPER(DllExample, special://xbmcbin/system/Example.dll)
445 // LOAD_SYMBOLS() // add this if you want to load debug symbols for the dll
446 // DEFINE_METHOD2(void, foo, (int p1, char* p2))
447 // DEFINE_METHOD_LINKAGE2(void, __stdcall, bar, (char* p1, int p2))
448 // DEFINE_METHOD_FP(void, foobar, (int type, char* szTest)) // No need to define this function in the
449 // // interface class, as it's a function pointer.
450 // // But its not recognised by IntelliSence
451 // BEGIN_METHOD_RESOLVE()
452 // RESOLVE_METHOD(foo)
453 // RESOLVE_METHOD_RENAME("_bar@8", bar)
454 // RESOLVE_METHOD_FP(foobar)
455 // END_METHOD_RESOLVE()
458 // The above macros will expand to a class that will look like this
460 // class DllExample : public DllDynamic, DllExampleInterface
463 // DllExample() : DllDynamic( "special://xbmcbin/system/Example.dll" ) {}
465 // virtual bool LoadSymbols() { return true; }
467 // typedef void (* foo_METHOD) ( int p1, char* p2 );
470 // virtual void foo( int p1, char* p2 )
472 // return m_foo(p1, p2);
475 // typedef void (__stdcall * bar_METHOD) ( char* p1, int p2 );
478 // virtual void bar( char* p1, int p2 )
480 // return m_bar(p1, p2);
483 // typedef void (* foobar_METHOD) (int type, char* szTest);
485 // foobar_METHOD foobar;
487 // virtual bool ResolveExports()
490 // m_dll->ResolveExport( "foo", (void**)& m_foo ) &&
491 // m_dll->ResolveExport( "_bar@8", (void**)& m_bar ) &&
492 // m_dll->ResolveExport( "foobar" , (void**)& foobar ) &&
498 // Usage of the class
502 // if (dll.IsLoaded())
504 // dll.foo(1, "bar");
509 ///////////////////////////////////////////////////////////
511 // Baseclass for a Dynamically loaded dll
512 // use the above macros to create a dll wrapper
518 explicit DllDynamic(const std::string
& strDllName
);
519 virtual ~DllDynamic();
521 virtual void Unload();
522 virtual bool IsLoaded() const { return m_dll
!=NULL
; }
524 bool EnableDelayedUnload(bool bOnOff
);
525 bool SetFile(const std::string
& strDllName
);
526 const std::string
&GetFile() const { return m_strDllName
; }
529 virtual bool ResolveExports()=0;
530 virtual bool LoadSymbols() { return false; }
532 LibraryLoader
* m_dll
;
533 std::string m_strDllName
;