DLL中獲取類封裝

做爲C++新手,在項目中寫一個動態加載的codec的程序,由於要考慮動態類的加載,因此對於dll文件進行了一些嘗試處理。函數

主要問題是dll文件的加載函數沒有提取class或是對象的接口,所以只能經過全局函數解決。ui


代碼以下:code

1, 定義codec的接口:對象

class ICodec
{
public:
    virtual status_t open() = 0;
    virtual void close() = 0;
    virtual sp<Message> query() =0;
    virtual status_t control() = 0;
    virtual status_t process() = 0;
};繼承

定義這個接口的目的是使dll可以經過繼承ICodec接口,從而在調用者不知道dll中codec的具體細節的狀況下,向外提供codec的功能
接口


2. DLL的實現get

MyCodec gMyCodec;

status_t MyCodec::open( const sp<Message>& params)
{
    cout<<"call MyCodec.open successfully"<<endl;
    return OK;
}
void MyCodec::close()
{
    cout<<"call MyCodec.close successfully"<<endl;
}
sp<Message> MyCodec::query()
{
    cout<<"call MyCodec.query successfully"<<endl;
    return NULL;
}
status_t MyCodec::control( ECmd eCmd, sp<Message>& params)
{
    cout<<"call MyCodec.control successfully"<<endl;
    return GENERAL_ERROR;
}
status_t MyCodec::process( const sp<Buffer>&src, BufferVecs& dst, uint32_t flags)
{
    cout<<"call MyCodec.process successfully"<<endl;
    return GENERAL_ERROR;
}

extern "C"
    TXBASE_API ICodec* getCodec()
{
    return &gMyCodec;
}it

利用最後的getCodec,傳出MyCodec的對象,而這個對象是派生自ICodec的,所以外部調用者能夠直接看成ICodec操做。io


3. 在外部調用時,封裝dll提供的功能ast

typedef ICodec* (*CODEC_GETTER)();


//class Dynamic: public ICodec

status_t DynamicCodec::open( const sp<Message>& params)
    {
        if (mDllCodec != NULL)
        {
            mDllCodec->open(params);
        }
        else
        {
            return NO_INIT;
        }
    }
    void DynamicCodec::close()
    {
        if (mDllCodec != NULL)
        {
            mDllCodec->close();
        }
        else
        {
            return;
        }
    }
    sp<Message> DynamicCodec::query()
    {
        if (mDllCodec != NULL)
        {
            return mDllCodec->query();
        }
        else
        {
            return NULL;
        }
    }
    status_t DynamicCodec::control( ECmd eCmd, sp<Message>& params)
    {
        if (mDllCodec != NULL)
        {
            mDllCodec->control(eCmd, params);
        }
        else
        {
            return NO_INIT;
        }
    }
    status_t DynamicCodec::process( const sp<Buffer>&src, BufferVecs& dst, uint32_t flags)
    {
        if (mDllCodec != NULL)
        {
            mDllCodec->process(src, dst, flags);
        }
        else
        {
            return NO_INIT;
        }

    }

    status_t DynamicCodec::init(const char* dllPath)
    {
        mModule = LoadLibraryW(dllPath);       //HINSTANCE mModule
        if (NULL == mModule)
        {
            return NAME_NOT_FOUND;
        }

        CODEC_GETTER getter = (CODEC_GETTER)dl_findSymbol(mModule, "getCodec");
        //class twl::ICodec * twl::getCodec(void)


        if (NULL == getter)
        {
            DWORD word = GetLastError();
            LOGE("failed to load function from dll, errorCode: %d",  word);
            return NAME_NOT_FOUND;
        }

        mDllCodec = (*getter)();
        if (NULL == mDllCodec)
        {
            FreeLibrary(mModule);
            return GENERAL_ERROR;
        }
        else
        {
            return OK;
        }
    }

    void DynamicCodec::clear()
    {
        mDllCodec->close();
        FreeLibrary(mModule);
    }


經過Dynamic類的實例化,完成方法調用的傳遞,從而至關於利用dll中的類MyCodec。

相關文章
相關標籤/搜索