用一个类来封装DLL(SO)的动态调用

 

动态调用DLL技术很常见也没有什么特别困难的,但是我总是感觉写起来很烦,要用typedef定义,加载DLL、查找地址,很烦人,所以我找了一个方式,把DLL动态调用的逻辑都封装成了一个类,使用起来就简单多了。

 

直接动态调用的方法,示例如下:

 

1、预定义

 

typedef LinphoneCore* (*funlinphone_core_new)(const LinphoneCoreVTable *vtable,const char *config_path, const char *factory_config, void* userdata);

 

2、定义函数指针变量

funlinphone_core_new pfn_core_new  ;

 

3、动态加载函数

handle = LoadLibrary( "liblinphone-4.dll");

pfn_core_new = (funlinphone_core_new)GetProcAddress( handle,"linphone_core_new");

 

4、调用

 

pfn_core_new(....);

 

 

 

 

这样调用就完成了,还得负责清理(函数指针指向NULL,卸载DLL等工作)。

 

使用类封装,先要使用下面一个类(添加到工程即可)

 

/****************************************************************************
*                                 DEFINE_PROC
* Inputs:
*       result: The result type; if a linkage type such as WINAPI, CALLBACK,
*        etc. is required, use DEFINE_PROC_LINKAGE
*    name: The function name
*    args: The argument list, enclosed in parentheses
* Notes:
*       There are as many of these as required for your methods to be called
****************************************************************************/

#define DEFINE_PROC(result, name, args) \
    protected: \
        typedef result (*name##_PROC) args; \
    public: \
        name##_PROC name;

/****************************************************************************
*                             DEFINE_PROC_LINKAGE
* Inputs:
*       result: Result type
*    linkage: Linkage type, e.g., CALLBACK, WINAPI
*    name: Function name
*    args: Argument list enclosed in ( )s
* Notes:
*       There are as many of these as required for your methods to be called
****************************************************************************/

#define DEFINE_PROC_LINKAGE(result, linkage, name, args) \
     protected: \
        typedef result (linkage * name##_PROC) args; \
     public: \
    name##_PROC name;

/****************************************************************************
*                               IMPLEMENT_PROC
* Inputs:
*       name: The name of the function, as used as the second argument of
*        DEFINE_PROC.
* Notes:
*       This must appear between a BEGIN_PROC_TABLE and END_PROC_TABLE
****************************************************************************/

#define IMPLEMENT_PROC(name) \
    IMPLEMENT_PROC_SPECIAL(name, #name)

/****************************************************************************
*                           IMPLEMENT_PROC_SPECIAL
* Inputs:
*       name: The name as defined by IMPLEMENT_PROC or IMPLEMENT_PROC_LINKAGE
*    externalname: The external name
* Notes:
*       This must appear between a BEGIN_PROC_TABLE and END_PROC_TABLE
****************************************************************************/

#define IMPLEMENT_PROC_SPECIAL(name, externalname) \
    name = loading ? (name##_PROC)GetProcAddress(library, externalname) : NULL; \
    { \
     DWORD err = ::GetLastError(); \
     if(loading) \
    ASSERT(name != NULL); \
     if(loading && name == NULL) \
       { \
    ::SetLastError(err); \
       } \
    }

/****************************************************************************
*                              BEGIN_PROC_TABLE
*                END_PROC_TABLE
* Effect:
*       This declares the method that initializes the method pointers.
*    There can be only one BEGIN_PROC_TABLE declaration per class.
*    Following this are some number of IMPLEMENT_PROC lines,
*    followed by END_PROC_TABLE
****************************************************************************/

#define BEGIN_PROC_TABLE() protected: virtual BOOL Define(BOOL loading) { ::SetLastError(ERROR_SUCCESS);
#define END_PROC_TABLE()   return TRUE; }

/****************************************************************************
*                              DECLARE_PROC_DLL
* Inputs:
*       myclass: The name of your subclass. This must be the same as
*          the class name you used to declare the class
*    superclass: This allows you to derive additional subclasses;
*        normally you will use the DynamicDLL class here
* Effect:
*       Defines the constructors and destructors for the subclass
****************************************************************************/

#define DECLARE_PROC_DLL(myclass, superclass) \
   public: \
       myclass() : superclass() {} \
       myclass(LPCTSTR module) : superclass(module) { Load(module); } \
       virtual ~myclass() { Free(); }
                     

/****************************************************************************
*                                 DynamicDLL
*       This is the abstract superclass on which all other classes are based
*    It defines the basic behavior of the class.
****************************************************************************/

class DynamicDLL {
    public:
       DynamicDLL() { Init(); }
       DynamicDLL(LPCTSTR name) { Init(); }
       virtual ~DynamicDLL() { }
       BOOL Load(LPCTSTR name) { ::SetLastError(ERROR_SUCCESS);
                 ASSERT(library == NULL); // Attempt to load twice?
                 if(library != NULL)
                    { /* already loaded */
                     //::SetLastError(ERROR_INVALID_HANDLE);
                     return FALSE;
                    } /* already loaded */
                                 library = ::LoadLibrary(name);
                 if(library != NULL)
                    return Define(TRUE);
                 Free();
                 return FALSE;
       }
       void Free() {if(library != NULL)
                   ::FreeLibrary(library);
                    library = NULL;
            Define(FALSE); }
       BOOL IsLoaded() { return library != NULL; }
    protected:
       void Init( ) { library = NULL; }
       HINSTANCE library;
       virtual BOOL Define(BOOL loading) { ASSERT(FALSE); return FALSE; } // must define in subclass
                          // Did you forget to do a BEGIN_PROC_TABLE?
};

/****************************************************************************
*                                   Example
****************************************************************************/
//class TestDynDLL: public DynamicDLL {
//   DECLARE_PROC_DLL(TestDynDLL, DynamicDLL)
//
//     DEFINE_PROC(LRESULT, Test, (LPCTSTR, int))
//     DEFINE_PROC_LINKAGE(BOOL, WINAPI, Test2, ( ) )
//
//     BEGIN_PROC_TABLE()
//         IMPLEMENT_PROC(Test)
//         IMPLEMENT_PROC_SPECIAL(Test2, "_Test2@0")
//     END_PROC_TABLE()
//
//};

 

有了这个类,就可以作为封装DLL调用的基础。

 

示例如下,例如调用windows中,user32.dll中的函数MessageBoxA,步骤如下:

 

首先,建立一个新的类,继承DynamicDLL类,在其中,声明所需使用的函数:

 

#include "DynamicDLL.h"

class TestDynDLL: public DynamicDLL {
    DECLARE_PROC_DLL(TestDynDLL, DynamicDLL)
       
        DEFINE_PROC_LINKAGE(int, WINAPI, MessageBoxA, ( HWND,LPCSTR,LPCSTR,UINT) )
       
        BEGIN_PROC_TABLE()
        IMPLEMENT_PROC(MessageBoxA)

        END_PROC_TABLE()
};

 

 

 

在需要调用的地方,调用上面这个类:

 

    TestDynDLL * DLL;
    DLL = new TestDynDLL(_T("user32.dll"));
    ASSERT(DLL->IsLoaded());
    int rr = DLL->MessageBoxA(this->GetSafeHwnd(),(LPCSTR)"22",(LPCSTR)"dsasdsa",MB_OK);
    delete DLL;

 

 

怎么样,是不是感觉好用多了?我没有在Linux下面测,估计稍加改动,Linux也能使用这种机制。

 

需要注意的是,在继承类中的这个声明,需要仔细写,函数名、参数、返回值、调用约定都需要保持一致,否则会出错的哦。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值