zoukankan      html  css  js  c++  java
  • 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) 
        { 
          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
    /*
     *      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 *)=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对方的头文件包含宏,这样就可以任意次在不同的头文件中

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

  • 相关阅读:
    OC面向对象—封装
    OC内存管理
    OC方法和文件编译
    OC语言基础知识
    OC语言前期准备
    C语言指针基础
    C语言字符串
    C语言数组
    C语言内存分析
    C语言函数
  • 原文地址:https://www.cnblogs.com/eaglexmw/p/3477368.html
Copyright © 2011-2022 走看看