xbmc的静态链接办法

XBMC是一个相当酷的音频/视频播放器,号称家庭影视中心。

我是希望静态将一些库链接进可执行程序的,这样我用的ArchLinux就不用天天在更新一些东西了

但XBMC试了很多次,编译成功后,总是在运行是段错误。

后面没办法,走读代码发现XBMC使用了一个很巧妙的办法实现动态链接库的载入。

XBMC定义了一个动态链接类DllDynamic,其中定义了Load/UnLoad/IsLoaded/ResolveExports几个接口

然后定义了一堆宏用于新类继承DllDynamic实现指定库的动态载入。

xbmc的静态链接办法
#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, ~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 bool ResolveExports() \

  { \

    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

//

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()=0;

  virtual bool LoadSymbols() { return false; }

  bool  m_DelayUnload;

  LibraryLoader* m_dll;

  CStdString m_strDllName;

};
DynamicDll.h
xbmc的静态链接办法
/*

 *      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,按指定格式定义函数接口后,就可以较轻易的实现动态链接一个新库

比如:

xbmc的静态链接办法
#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 *)=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 : 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()

};
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; return ResolveExports(); }    \

  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对方的头文件包含宏,这样就可以任意次在不同的头文件中

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

 

 

你可能感兴趣的:(静态)