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) \
{ \
return m_##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: \
virtual result name args \
{ \
return m_##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: \
virtual result name##args #define DEFINE_FUNC_PART2(size) \
{ \
int o,s = size; \
__asm { \
__asm mov [o], esp \
__asm sub esp, [s] \
__asm and esp, ~ \
__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() \
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 bool ResolveExports() \
{ \
return ( #define END_METHOD_RESOLVE() \
\
); \
} ///////////////////////////////////////////////////////////
//
// 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
//
class DllDynamic
{
public:
DllDynamic();
DllDynamic(const CStdString& strDllName);
virtual ~DllDynamic();
virtual bool Load();
virtual void Unload();
virtual bool IsLoaded() { return m_dll!=NULL; }
bool CanLoad();
bool EnableDelayedUnload(bool bOnOff);
bool SetFile(const CStdString& strDllName); protected:
virtual bool ResolveExports()=;
virtual bool LoadSymbols() { return false; }
bool m_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 namespace XFILE; 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();
} bool DllDynamic::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;
} void DllDynamic::Unload()
{
if(m_dll)
CSectionLoader::UnloadDLL(m_strDllName);
m_dll=NULL;
} bool DllDynamic::CanLoad()
{
return CFile::Exists(m_strDllName);
} bool DllDynamic::EnableDelayedUnload(bool bOnOff)
{
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" class DllLibMadInterface
{
public:
virtual ~DllLibMadInterface() {}
virtual void mad_synth_init(struct mad_synth *)=;
virtual void mad_stream_init(struct mad_stream *)=;
virtual void mad_frame_init(struct mad_frame *)=;
virtual void mad_stream_finish(struct mad_stream *)=;
virtual void mad_frame_finish(struct mad_frame *)=;
virtual void mad_stream_buffer(struct mad_stream *, unsigned char const *, unsigned long)=;
virtual void mad_synth_frame(struct mad_synth *, struct mad_frame const *)=;
virtual int mad_frame_decode(struct mad_frame *, struct mad_stream *)=;
virtual int mad_stream_sync(struct mad_stream *) = ;
virtual char const* mad_stream_errorstr(struct mad_stream const *) = ;
virtual void mad_frame_mute(struct mad_frame *) = ;
virtual void mad_synth_mute(struct mad_synth *) = ;
virtual void mad_timer_add(mad_timer_t *, mad_timer_t) = ;
virtual mad_timer_t Get_mad_timer_zero() = ;
}; class DllLibMad : public DllDynamic, 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 long p3))
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()
};

想实现静态链接库进来,就得在类继承这儿动手脚

我写了两个头文件,如下:

#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*); return ResolveExports(); } \
virtual void Unload() { m_dll = ; } #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对方的头文件包含宏,这样就可以任意次在不同的头文件中

成对使用这两个头文件包含了

xbmc的静态链接办法的更多相关文章

  1. GCC 编译使用动态链接库和静态链接库

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有 ...

  2. boost静态链接的问题 -lgcc_s

    在使用gcc/g++ 编译程序时我们希望指向一些库是使用静态的链接方式. 另外的一些是动态的方式. 我以boost 为例. 如果我们要使用静态库则是这样的: # g++ main.cpp -lpthr ...

  3. 动态链接库dll,静态链接库lib, 导入库lib

    转载地址:http://www.cnblogs.com/chio/archive/2008/08/05/1261296.html 目前以lib后缀的库有两种,一种为静态链接库(Static Libar ...

  4. GCC 编译使用动态链接库和静态链接库的方法

    1 库的分类 依据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的.所以生成的可执行文件就不受库的影响了.即使库被删除了,程序依旧能够成功执行. 有别于静态库,动态库的链接是在程 ...

  5. 动态链接库dll,导入库lib,静态链接库lib

    目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库” ...

  6. 【转】gcc 编译使用动态链接库和静态链接库

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有 ...

  7. GCC编译过程与动态链接库和静态链接库

    1. 库的介绍 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式,可 ...

  8. [转载]GCC 编译使用动态链接库和静态链接库--及先后顺序----及环境变量设置总结

    来自http://blog.csdn.net/benpaobagzb/article/details/51364005 GCC 编译使用动态链接库和静态链接库 1 库的分类 根据链接时期的不同,库又有 ...

  9. 静态链接和动态链接库混用导致的链接错误LINK2005

    对于一个静态链接库L.lib,它的使用者app.exe会静态链接L.lib,意思是app.exe会将L.lib中的代码(app需要的部分,例如函数定义,类的定义等等)链接到app.exe中.   而对 ...

随机推荐

  1. Crowdsourcing(众包)

    群众外包(英语:crowdsourcing)是互联网带来的新的生产组织形式.<连线>(Wired)杂志记者Jeff Howe于2006年发明的一个专业术语,用来描述一种新的商业模式,即企业 ...

  2. python2.7到python3代码转换脚本2to3的一些介绍

       你的位置: Home ‣ Dive Into Python 3 ‣ 难度等级: ♦♦♦♦♦   使用2to3将代码移植到Python 3 ❝ Life is pleasant. Death is ...

  3. asp.net MVC添加HtmlHelper扩展示例和用法

    一.先创建一个HtmlHelper的扩展类,代码: using System; using System.Collections.Generic; using System.Linq; using S ...

  4. centos 7 下进入单用户模式修改root密码

    centos7进入单用户模式修改root用户密码 在工作中可能会遇到root密码忘记,那么这里就要进入单用户模式下了. 在重启电脑之后 时间:2015-05-13 10:42来源:blog.51cto ...

  5. linux 设置日志编码

    打开linux的设置面板 在Appearance选项->Character encoding 设置为UTF-8

  6. 理解 Mybatis的分页插件 PageHelper

    Mybatis + SpringMVC + Maven实现分页查询 (推荐采用的插件是PageHelper) 先看一下之前的这篇博客,这里推荐了 Mybatis 的分页方法. 按照上面的方法设置后,确 ...

  7. lucene-Field.Store解析

    本文主要内容装载这里 Store 三种形态 COMPRESS:压缩保存.用于长文本或二进制数据 (后期高版本舍弃了) YES:保存 NO:不保存 具体案例 package demo.first; im ...

  8. js学习笔记3---自定义属性

    1.自定义属性-----JS可以为任何 HTML元素 添加 任意个 自定义属性 方法:元素.属性 = 属性值 如:aBtn[0].abc = 123; 2.添加索引值,匹配数组 for(i=0; i& ...

  9. Web前端性能优化教程05:网站样式和脚本

    本文是Web前端性能优化系列文章中的第五篇,主要讲述内容:网站样式和脚本代码的放置位置.使用外部javascript和css.完整教程可查看:Web前端性能优化 一.将样式表放在顶部 可视性回馈的重要 ...

  10. 优先队列priority_queue的比较函数

    STL头文件:#include<queue> 优先队列: 默认从大到小排列:priority_queuee<node>q; 自定义优先级的三种方法: 1.重载操作符: bool ...