xbmc的静态链接办法
XBMC是一个相当酷的音频/视频播放器,号称家庭影视中心。
我是希望静态将一些库链接进可执行程序的,这样我用的ArchLinux就不用天天在更新一些东西了
但XBMC试了很多次,编译成功后,总是在运行是段错误。
后面没办法,走读代码发现XBMC使用了一个很巧妙的办法实现动态链接库的载入。
XBMC定义了一个动态链接类DllDynamic,其中定义了Load/UnLoad/IsLoaded/ResolveExports几个接口
然后定义了一堆宏用于新类继承DllDynamic实现指定库的动态载入。

#pragma once /** Copyright (C) 2005-2012 Team XBMC
*http://www.xbmc.org*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
**/#include"cores/DllLoader/LibraryLoader.h"#include"utils/StdString.h"#include"DllPaths.h" /////////////////////////////////////////////////////////// // //DECLARE_DLL_WRAPPER// //Declares the constructor of the wrapper class.//This must be followed by one or more//DEFINE_METHODX/DEFINE_METHOD_LINKAGEX and//one BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE block.// //classname: name of the wrapper class to construct//dllname: file including path of the dll to wrap #define DECLARE_DLL_WRAPPER(classname, dllname) \XDECLARE_DLL_WRAPPER(classname,dllname)#define XDECLARE_DLL_WRAPPER(classname, dllname) \ public: \
classname () : DllDynamic( dllname ) {}/////////////////////////////////////////////////////////// // //DECLARE_DLL_WRAPPER_TEMPLATE_BEGIN// //Declares the constructor of the wrapper class.//The method SetFile(strDllName) can be used to set the//dll of this wrapper.//This must be followed by one or more//DEFINE_METHODX/DEFINE_METHOD_LINKAGEX and//one BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE block.// //classname: name of the wrapper class to construct//#define DECLARE_DLL_WRAPPER_TEMPLATE(classname) \ public: \
classname () {} \/////////////////////////////////////////////////////////// // //LOAD_SYMBOLS// //Tells the dllloader to load Debug symblos when possible #define LOAD_SYMBOLS() \ protected: \virtual bool LoadSymbols() { return true; }/////////////////////////////////////////////////////////// // //DEFINE_GLOBAL// //Defines a global for export from the dll as well as//a function for accessing it (Get_name).// //type: The variables type.//name: Name of the variable.// #define DEFINE_GLOBAL_PTR(type, name) \ protected: \
union { \
type*m_##name; \void*m_##name##_ptr; \
}; \public: \virtual type* Get_##name (void) \
{ \returnm_##name; \
}#define DEFINE_GLOBAL(type, name) \ protected: \
union { \
type*m_##name; \void*m_##name##_ptr; \
}; \public: \virtual type Get_##name (void) \
{ \return *m_##name; \
}/////////////////////////////////////////////////////////// // //DEFINE_METHOD_LINKAGE// //Defines a function for an export from a dll, if the//calling convention is not __cdecl.//Use DEFINE_METHOD_LINKAGE for each function to be resolved.// //result: Result of the function//linkage: Calling convention of the function//name: Name of the function//args: Arguments of the function, enclosed in parentheses//#define DEFINE_METHOD_LINKAGE_FP(result, linkage, name, args) \ protected: \
typedef result (linkage*name##_METHOD) args; \public: \
union { \
name##_METHOD name; \void*name##_ptr; \
};#define DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, args2) \ protected: \
typedef result (linkage*name##_METHOD) args; \
union { \
name##_METHOD m_##name; \void*m_##name##_ptr; \
}; \public: \virtualresult name args \
{ \returnm_##name args2; \
}#define DEFINE_METHOD_LINKAGE0(result, linkage, name) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, () , ())#define DEFINE_METHOD_LINKAGE1(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1))#define DEFINE_METHOD_LINKAGE2(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2))#define DEFINE_METHOD_LINKAGE3(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3))#define DEFINE_METHOD_LINKAGE4(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4))#define DEFINE_METHOD_LINKAGE5(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5))#define DEFINE_METHOD_LINKAGE6(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6))#define DEFINE_METHOD_LINKAGE7(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7))#define DEFINE_METHOD_LINKAGE8(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8))#define DEFINE_METHOD_LINKAGE9(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8, p9))#define DEFINE_METHOD_LINKAGE10(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))#define DEFINE_METHOD_LINKAGE11(result, linkage, name, args) \DEFINE_METHOD_LINKAGE_BASE(result, linkage, name, args, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11))/////////////////////////////////////////////////////////// // //DEFINE_METHOD_FP// //Defines a function for an export from a dll as a fuction pointer.//Use DEFINE_METHOD_FP for each function to be resolved. Functions//defined like this are not listed by IntelliSence.// //result: Result of the function//name: Name of the function//args: Arguments of the function, enclosed in parentheses//The parameter names can be anything//#define DEFINE_METHOD_FP(result, name, args) DEFINE_METHOD_LINKAGE_FP(result, __cdecl, name, args) /////////////////////////////////////////////////////////// // //DEFINE_METHODX// //Defines a function for an export from a dll.//Use DEFINE_METHODX for each function to be resolved.//where X is the number of parameter the function has.// //result: Result of the function//name: Name of the function//args: Arguments of the function, enclosed in parentheses//The parameter names have to be renamed to px, where//x is the number of the parameter//#define DEFINE_METHOD0(result, name) DEFINE_METHOD_LINKAGE0(result, __cdecl, name) #define DEFINE_METHOD1(result, name, args) DEFINE_METHOD_LINKAGE1(result, __cdecl, name, args) #define DEFINE_METHOD2(result, name, args) DEFINE_METHOD_LINKAGE2(result, __cdecl, name, args) #define DEFINE_METHOD3(result, name, args) DEFINE_METHOD_LINKAGE3(result, __cdecl, name, args) #define DEFINE_METHOD4(result, name, args) DEFINE_METHOD_LINKAGE4(result, __cdecl, name, args) #define DEFINE_METHOD5(result, name, args) DEFINE_METHOD_LINKAGE5(result, __cdecl, name, args) #define DEFINE_METHOD6(result, name, args) DEFINE_METHOD_LINKAGE6(result, __cdecl, name, args) #define DEFINE_METHOD7(result, name, args) DEFINE_METHOD_LINKAGE7(result, __cdecl, name, args) #define DEFINE_METHOD8(result, name, args) DEFINE_METHOD_LINKAGE8(result, __cdecl, name, args) #define DEFINE_METHOD9(result, name, args) DEFINE_METHOD_LINKAGE9(result, __cdecl, name, args) #define DEFINE_METHOD10(result, name, args) DEFINE_METHOD_LINKAGE10(result, __cdecl, name, args) #define DEFINE_METHOD11(result, name, args) DEFINE_METHOD_LINKAGE11(result, __cdecl, name, args)#ifdef _MSC_VER/////////////////////////////////////////////////////////// // //DEFINE_FUNC_ALIGNED 0-X// //Defines a function for an export from a dll, wich//require a aligned stack on function call//Use DEFINE_FUNC_ALIGNED for each function to be resolved.// //result: Result of the function//linkage: Calling convention of the function//name: Name of the function//args: Argument types of the function// //Actual function call will expand to something like this//this will align the stack (esp) at the point of function//entry as required by gcc compiled dlls, it is abit abfuscated//to allow for different sized variables// //int64_t test(int64_t p1, char p2, char p3)//{//int o,s = ((sizeof(p1)+3)&~3)+((sizeof(p2)+3)&~3)+((sizeof(p3)+3)&~3);//__asm mov [o],esp;//__asm sub esp, [s];//__asm and esp, ~15;//__asm add esp, [s]//m_test(p1, p2, p3);//return value will still be correct aslong as we don't mess with it//__asm mov esp,[o];//}; #define ALS(a) ((sizeof(a)+3)&~3) #define DEFINE_FUNC_PART1(result, linkage, name, args) \ private: \
typedef result (linkage*name##_type)##args; \
union { \
name##_type m_##name; \void*m_##name##_ptr; \
}; \public: \virtualresult name##args#define DEFINE_FUNC_PART2(size) \{ \int o,s =size; \
__asm { \
__asm mov [o], esp \
__asm sub esp, [s] \
__asm and esp,~15\
__asm add esp, [s] \
}#define DEFINE_FUNC_PART3(name,args) \m_##name##args; \
__asm { \
__asm mov esp,[o] \
} \
}#define DEFINE_FUNC_ALIGNED0(result, linkage, name) \DEFINE_FUNC_PART1(result, linkage, name, ()) \
DEFINE_FUNC_PART2(0) \
DEFINE_FUNC_PART3(name,())#define DEFINE_FUNC_ALIGNED1(result, linkage, name, t1) \DEFINE_FUNC_PART1(result, linkage, name, (t1 p1)) \
DEFINE_FUNC_PART2(ALS(p1)) \
DEFINE_FUNC_PART3(name,(p1))#define DEFINE_FUNC_ALIGNED2(result, linkage, name, t1, t2) \DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2)) \
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)) \
DEFINE_FUNC_PART3(name,(p1, p2))#define DEFINE_FUNC_ALIGNED3(result, linkage, name, t1, t2, t3) \DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3)) \
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)) \
DEFINE_FUNC_PART3(name,(p1, p2, p3))#define DEFINE_FUNC_ALIGNED4(result, linkage, name, t1, t2, t3, t4) \DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4)) \
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)) \
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4))#define DEFINE_FUNC_ALIGNED5(result, linkage, name, t1, t2, t3, t4, t5) \DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5)) \
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)) \
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5))#define DEFINE_FUNC_ALIGNED6(result, linkage, name, t1, t2, t3, t4, t5, t6) \DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6)) \
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)) \
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6))#define DEFINE_FUNC_ALIGNED7(result, linkage, name, t1, t2, t3, t4, t5, t6, t7) \DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7)) \
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)+ALS(p7)) \
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6, p7))#define DEFINE_FUNC_ALIGNED8(result, linkage, name, t1, t2, t3, t4, t5, t6, t7, t8) \DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8)) \
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)+ALS(p7)+ALS(p8)) \
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6, p7, p8))#define DEFINE_FUNC_ALIGNED9(result, linkage, name, t1, t2, t3, t4, t5, t6, t7, t8, t9) \DEFINE_FUNC_PART1(result, linkage, name, (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9)) \
DEFINE_FUNC_PART2(ALS(p1)+ALS(p2)+ALS(p3)+ALS(p4)+ALS(p5)+ALS(p6)+ALS(p7)+ALS(p8)+ALS(p9)) \
DEFINE_FUNC_PART3(name,(p1, p2, p3, p4, p5, p6, p7, p8, p9))#else #define DEFINE_FUNC_ALIGNED0(result, linkage, name) DEFINE_METHOD_LINKAGE0 (result, linkage, name) #define DEFINE_FUNC_ALIGNED1(result, linkage, name, t1) DEFINE_METHOD_LINKAGE1 (result, linkage, name, (t1 p1) ) #define DEFINE_FUNC_ALIGNED2(result, linkage, name, t1, t2) DEFINE_METHOD_LINKAGE2 (result, linkage, name, (t1 p1, t2 p2) ) #define DEFINE_FUNC_ALIGNED3(result, linkage, name, t1, t2, t3) DEFINE_METHOD_LINKAGE3 (result, linkage, name, (t1 p1, t2 p2, t3 p3) ) #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) ) #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) ) #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) ) #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) ) #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) ) #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) ) #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) ) #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) ) #endif /////////////////////////////////////////////////////////// // //BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE// //Defines a method that resolves the exported functions//defined with DEFINE_METHOD or DEFINE_METHOD_LINKAGE.//There must be a RESOLVE_METHOD or RESOLVE_METHOD_RENAME//for each DEFINE_METHOD or DEFINE_METHOD_LINKAGE within this//block. This block must be followed by an END_METHOD_RESOLVE.//#define BEGIN_METHOD_RESOLVE() \ protected: \virtual boolResolveExports() \
{ \return(#define END_METHOD_RESOLVE() \ 1\
); \
}/////////////////////////////////////////////////////////// // //RESOLVE_METHOD// //Resolves a method from a dll// //method: Name of the method defined with DEFINE_METHOD//or DEFINE_METHOD_LINKAGE//#define RESOLVE_METHOD(method) \m_dll->ResolveExport( #method , & m_##method##_ptr ) && #define RESOLVE_METHOD_FP(method) \m_dll->ResolveExport( #method , & method##_ptr ) && /////////////////////////////////////////////////////////// // //RESOLVE_METHOD_RENAME// //Resolves a method from a dll// //dllmethod: Name of the function exported from the dll//method: Name of the method defined with DEFINE_METHOD//or DEFINE_METHOD_LINKAGE//#define RESOLVE_METHOD_RENAME(dllmethod, method) \m_dll->ResolveExport( #dllmethod , & m_##method##_ptr ) && #define RESOLVE_METHOD_RENAME_FP(dllmethod, method) \m_dll->ResolveExport( #dllmethod , & method##_ptr ) && //////////////////////////////////////////////////////////////////// // //Example declaration of a dll wrapper class// //1. Define a class with pure virtual functions with all functions//exported from the dll. This is needed to use the IntelliSence//feature of the Visual Studio Editor.// //class DllExampleInterface//{//public://virtual void foo (unsigned int type, char* szTest)=0;//virtual void bar (char* szTest, unsigned int type)=0;//};// //2. Define a class, derived from DllDynamic and the previously defined//interface class. Define the constructor of the class using the//DECLARE_DLL_WRAPPER macro. Use the DEFINE_METHODX/DEFINE_METHOD_LINKAGEX//macros to define the functions from the interface above, where X is number of//parameters the function has. The function parameters//have to be enclosed in parentheses. The parameter names have to be changed to px//where x is the number on which position the parameter appears.//Use the RESOLVE_METHOD/RESOLVE_METHOD_RENAME to do the actually resolve the functions//from the dll when it's loaded. The RESOLVE_METHOD/RESOLVE_METHOD_RENAME have to//be between the BEGIN_METHOD_RESOLVE/END_METHOD_RESOLVE block.// //class DllExample : public DllDynamic, DllExampleInterface//{//DECLARE_DLL_WRAPPER(DllExample, special://xbmcbin/system/Example.dll)//LOAD_SYMBOLS()//add this if you want to load debug symbols for the dll//DEFINE_METHOD2(void, foo, (int p1, char* p2))//DEFINE_METHOD_LINKAGE2(void, __stdcall, bar, (char* p1, int p2))//DEFINE_METHOD_FP(void, foobar, (int type, char* szTest))//No need to define this function in the// //interface class, as it's a function pointer.// //But its not recognised by IntelliSence//BEGIN_METHOD_RESOLVE()//RESOLVE_METHOD(foo)//RESOLVE_METHOD_RENAME("_bar@8", bar)//RESOLVE_METHOD_FP(foobar)//END_METHOD_RESOLVE()//};// //The above macros will expand to a class that will look like this// //class DllExample : public DllDynamic, DllExampleInterface//{//public://DllExample() : DllDynamic( "special://xbmcbin/system/Example.dll" ) {}//protected://virtual bool LoadSymbols() { return true; }//protected://typedef void (* foo_METHOD) ( int p1, char* p2 );//foo_METHOD m_foo;//public://virtual void foo( int p1, char* p2 )//{//return m_foo(p1, p2);//}//protected://typedef void (__stdcall * bar_METHOD) ( char* p1, int p2 );//bar_METHOD m_bar;//public://virtual void bar( char* p1, int p2 )//{//return m_bar(p1, p2);//}//protected://typedef void (* foobar_METHOD) (int type, char* szTest);//public://foobar_METHOD foobar;//protected://virtual bool ResolveExports()//{//return (//m_dll->ResolveExport( "foo", (void**)& m_foo ) &&//m_dll->ResolveExport( "_bar@8", (void**)& m_bar ) &&//m_dll->ResolveExport( "foobar" , (void**)& foobar ) &&//1//);//}//};// //Usage of the class// //DllExample dll;//dll.Load();//if (dll.IsLoaded())//{//dll.foo(1, "bar");//dll.Unload();//}// /////////////////////////////////////////////////////////// // //Baseclass for a Dynamically loaded dll//use the above macros to create a dll wrapper//classDllDynamic
{public:
DllDynamic();
DllDynamic(const CStdString&strDllName);virtual ~DllDynamic();virtual boolLoad();virtual voidUnload();virtual bool IsLoaded() { return m_dll!=NULL; }boolCanLoad();bool EnableDelayedUnload(boolbOnOff);bool SetFile(const CStdString&strDllName);protected:virtual bool ResolveExports()=0;virtual bool LoadSymbols() { return false; }boolm_DelayUnload;
LibraryLoader*m_dll;
CStdString m_strDllName;
};
DynamicDll.h

/** Copyright (C) 2005-2012 Team XBMC
*http://www.xbmc.org*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
**/#include"DynamicDll.h"#include"SectionLoader.h"#include"filesystem/File.h"#include"utils/log.h" using namespaceXFILE;
DllDynamic::DllDynamic()
{
m_dll=NULL;
m_DelayUnload=true;
}
DllDynamic::DllDynamic(const CStdString&strDllName)
{
m_strDllName=strDllName;
m_dll=NULL;
m_DelayUnload=true;
}
DllDynamic::~DllDynamic()
{
Unload();
}boolDllDynamic::Load()
{if(m_dll)return true;if (!(m_dll=CSectionLoader::LoadDLL(m_strDllName, m_DelayUnload, LoadSymbols())))return false;if (!ResolveExports())
{
CLog::Log(LOGERROR,"Unable to resolve exports from dll %s", m_strDllName.c_str());
Unload();return false;
}return true;
}voidDllDynamic::Unload()
{if(m_dll)
CSectionLoader::UnloadDLL(m_strDllName);
m_dll=NULL;
}boolDllDynamic::CanLoad()
{returnCFile::Exists(m_strDllName);
}bool DllDynamic::EnableDelayedUnload(boolbOnOff)
{if(m_dll)return false;
m_DelayUnload=bOnOff;return true;
}bool DllDynamic::SetFile(const CStdString&strDllName)
{if(m_dll)return false;
m_strDllName=strDllName;return true;
}
DynamicDll.cpp
一个类继承自DllDynamic,按指定格式定义函数接口后,就可以较轻易的实现动态链接一个新库
比如:

#pragma once /** Copyright (C) 2005-2012 Team XBMC
*http://www.xbmc.org*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
**/ #if (defined HAVE_CONFIG_H) && (!defined WIN32)#include"config.h" #endif /*undefine byte from PlatformDefs.h since it's used in mad.h*/ #undef byte #if defined(_LINUX) || defined(TARGET_DARWIN)#include<mad.h> #else#include"libmad/mad.h" #endif#include"DynamicDll.h" classDllLibMadInterface
{public:virtual ~DllLibMadInterface() {}virtual void mad_synth_init(struct mad_synth *)=0;virtual void mad_stream_init(struct mad_stream *)=0;virtual void mad_frame_init(struct mad_frame *)=0;virtual void mad_stream_finish(struct mad_stream *)=0;virtual void mad_frame_finish(struct mad_frame *)=0;virtual void mad_stream_buffer(struct mad_stream *, unsigned char const *, unsigned long)=0;virtual void mad_synth_frame(struct mad_synth *, struct mad_frame const *)=0;virtual int mad_frame_decode(struct mad_frame *, struct mad_stream *)=0;virtual int mad_stream_sync(struct mad_stream *) = 0;virtual char const* mad_stream_errorstr(struct mad_stream const *) = 0;virtual void mad_frame_mute(struct mad_frame *) = 0;virtual void mad_synth_mute(struct mad_synth *) = 0;virtual void mad_timer_add(mad_timer_t *, mad_timer_t) = 0;virtual mad_timer_t Get_mad_timer_zero() = 0;
};class DllLibMad : publicDllDynamic, DllLibMadInterface
{
DECLARE_DLL_WRAPPER(DllLibMad, DLL_PATH_LIBMAD)
DEFINE_METHOD1(void, mad_synth_init, (struct mad_synth *p1))
DEFINE_METHOD1(void, mad_stream_init, (struct mad_stream *p1))
DEFINE_METHOD1(void, mad_frame_init, (struct mad_frame *p1))
DEFINE_METHOD1(void, mad_stream_finish, (struct mad_stream *p1))
DEFINE_METHOD1(void, mad_frame_finish, (struct mad_frame *p1))
DEFINE_METHOD3(void, mad_stream_buffer, (struct mad_stream * p1, unsigned char const *p2, unsigned longp3))
DEFINE_METHOD2(void, mad_synth_frame, (struct mad_synth *p1, struct mad_frame const *p2))
DEFINE_METHOD2(int, mad_frame_decode, (struct mad_frame *p1, struct mad_stream *p2))
DEFINE_METHOD1(int, mad_stream_sync, (struct mad_stream *p1))
DEFINE_METHOD1(void, mad_frame_mute, (struct mad_frame *p1))
DEFINE_METHOD1(void, mad_synth_mute, (struct mad_synth *p1))
DEFINE_METHOD2(void, mad_timer_add, (mad_timer_t *p1, mad_timer_t p2))
DEFINE_METHOD1(char const*, mad_stream_errorstr, (struct mad_stream const *p1))
DEFINE_GLOBAL(mad_timer_t, mad_timer_zero)
BEGIN_METHOD_RESOLVE()
RESOLVE_METHOD(mad_synth_init)
RESOLVE_METHOD(mad_stream_init)
RESOLVE_METHOD(mad_frame_init)
RESOLVE_METHOD(mad_stream_finish)
RESOLVE_METHOD(mad_frame_finish)
RESOLVE_METHOD(mad_stream_buffer)
RESOLVE_METHOD(mad_synth_frame)
RESOLVE_METHOD(mad_frame_decode)
RESOLVE_METHOD(mad_stream_sync)
RESOLVE_METHOD(mad_frame_mute)
RESOLVE_METHOD(mad_synth_mute)
RESOLVE_METHOD(mad_timer_add)
RESOLVE_METHOD(mad_stream_errorstr)
RESOLVE_METHOD(mad_timer_zero)
END_METHOD_RESOLVE()
};
View Code
想实现静态链接库进来,就得在类继承这儿动手脚
我写了两个头文件,如下:
#ifndef __DEF_STATIC_LIB_METHOD_H__#define __DEF_STATIC_LIB_METHOD_H__ #undef DECLARE_DLL_WRAPPER #undef XDECLARE_DLL_WRAPPER #undef RESOLVE_METHOD #undef RESOLVE_METHOD_FP #undef RESOLVE_METHOD_RENAME #undef RESOLVE_METHOD_RENAME_FP #define DECLARE_DLL_WRAPPER(classname, dllname) \XDECLARE_DLL_WRAPPER(classname,dllname)#define XDECLARE_DLL_WRAPPER(classname, dllname) \ public: \
classname () : DllDynamic( dllname ) {} \virtual bool Load() { if (m_dll) return true; m_dll = (LibraryLoader*)1; returnResolveExports(); } \virtual void Unload() { m_dll = 0; }#define RESOLVE_METHOD(method) \( m_##method##_ptr= (void*) & :: method ) && #define RESOLVE_METHOD_FP(method) \( method##_ptr= (void*) & :: method ) && #define RESOLVE_METHOD_RENAME(dllmethod, method) \( m_##method##_ptr= (void*) & :: dllmethod ) && #define RESOLVE_METHOD_RENAME_FP(dllmethod, method) \( method##_ptr= (void*) & :: dllmethod ) && #undef __DEF_SHARED_SO_METHOD_H__ #endif
#ifndef __DEF_SHARED_SO_METHOD_H__#define __DEF_SHARED_SO_METHOD_H__ #undef DECLARE_DLL_WRAPPER #undef XDECLARE_DLL_WRAPPER #undef RESOLVE_METHOD #undef RESOLVE_METHOD_FP #undef RESOLVE_METHOD_RENAME #undef RESOLVE_METHOD_RENAME_FP #define DECLARE_DLL_WRAPPER(classname, dllname) \XDECLARE_DLL_WRAPPER(classname,dllname)#define XDECLARE_DLL_WRAPPER(classname, dllname) \ public: \
classname () : DllDynamic( dllname ) {}#define RESOLVE_METHOD(method) \m_dll->ResolveExport( #method , & m_##method##_ptr ) && #define RESOLVE_METHOD_FP(method) \m_dll->ResolveExport( #method , & method##_ptr ) && #define RESOLVE_METHOD_RENAME(dllmethod, method) \m_dll->ResolveExport( #dllmethod , & m_##method##_ptr ) && #define RESOLVE_METHOD_RENAME_FP(dllmethod, method) \m_dll->ResolveExport( #dllmethod , & method##_ptr ) && #undef __DEF_STATIC_LIB_METHOD_H__ #endif
如何使用?
只需要在类定义之前包含def_static_lib_method.h,在之后再包含def_shared_so_method.h即可
静态链接的秘诀就在替换了RESOLVE_METHOD那几个宏,将函数调用替换成指针赋值
亮点在于,两个头文件,在末尾分别undef对方的头文件包含宏,这样就可以任意次在不同的头文件中
成对使用这两个头文件包含了