簡體   English   中英

動態鏈接C ++ DLL…我在做什么錯?

[英]Dynamic Linking C++ DLL … What am I doing wrong?

我一直在嘗試創建一個DLL並將DLL鏈接到我的程序,但是每次我嘗試我的程序都找不到該函數。 DLL加載正常,但是找不到該函數。

程序:

#include <iostream>
#include <windows.h>
using namespace std;

typedef void (*HelloPtr)();

int main() { 
    HelloPtr hello;
    HINSTANCE hDll = LoadLibrary("dll.dll");
    if(hDll)
    {
        hello = (HelloPtr)GetProcAddress(hDll, "hello");
        if(hello) {
            hello();
        } else {
            // Error code here
        }
    }
    return 0;   
}

dllmain.cpp

#include "dll.h"
#include <windows.h>

DLLIMPORT void hello()
{
   MessageBox(NULL, "Hey", "", MB_OK);          
}

DllClass::DllClass()
{

}

DllClass::~DllClass ()
{

}


BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
    switch (reason)
    {
        case DLL_PROCESS_ATTACH:
        break;

        case DLL_PROCESS_DETACH:
        break;

        case DLL_THREAD_ATTACH:
        break;

        case DLL_THREAD_DETACH:
        break;
    }

    /* Returns TRUE on success, FALSE on failure */
    return TRUE;
}

dll文件

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport) void hello(void)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllexport) void hello(void)
#endif /* Not BUILDING_DLL */

class DLLIMPORT DllClass
{
    public:
    DllClass();
    virtual ~DllClass(void);

    // Says hello world
    DLLImport void hello(void);

    private:

};


#endif /* _DLL_H_ */

我想知道我在做錯什么,所以我可以記錄下來並學習。

謝謝

您需要將DLL代碼放在extern "C"塊中,否則編譯器將破壞所有函數的名稱

看看這個問題以獲取更多信息: C ++ DLL導出:裝飾/拼寫的名稱

在dll中,將要導出的所有功能放到

    #ifdef __cplusplus
    extern "C" {
    #endif

   DLLIMPORT void hello()
   {
   MessageBox(NULL, "Hey", "", MB_OK);          
   }

    #ifdef __cplusplus
    } 
    #endif

出於明顯的原因,函數名稱在導出時會被篡改 如果使用函數重載怎么辦? 如果您在兩個不同的類中都有一個名為hello()的函數,該怎么辦? 例如,Qt的QString& remove(const QRegExp& rx)導出為?remove@QString@@QAEAAV1@ABVQRegExp@@@Z 解決此問題的最簡單方法是使用extern "C"和cdecl或stdcall導出函數,以使它們不被破壞(或以更標准/可預測的方式被破壞)。

你有:

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport) void hello(void)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllexport) void hello(void)
#endif /* Not BUILDING_DLL */

然后您有:

DLLIMPORT void hello()

組合將變成這樣,這沒有意義:

__declspec (dllexport) void hello(void) void hello()

將您的DLLIMPORT宏改為:

#if BUILDING_DLL
# define DLLIMPORT __declspec(dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec(dllimport)
#endif /* Not BUILDING_DLL */

編輯:您也有兩種情況下的dllexport; 較低的應該是dllimport。

您還已經在hello方法上使用了DLLImport而不是DLLIMPORT。

您也不能(或至少不應)在DLL中導出非靜態類成員。 如果要導出C ++類,我建議:

  1. 導出可在類對象上創建,銷毀和調用方法的DLL函數。 創建函數將返回類似HANDLE,void *或類似的不透明指針的內容。 其他方法會將其作為參數,將其強制轉換為實際值,然后在其上調用該方法。

  2. 使用COM。

您還應該遵循Sanja Melnichuk的建議,以避免修飾導出的函數名稱。

這是Dll.h的示例:

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT __declspec(dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec(dllimport)
#endif /* Not BUILDING_DLL */


extern "C"
{
    DLLIMPORT void hello(void);
}

請注意,DllClass已消失。 (您在dllmain.cpp中的hello函數保持不變,因為它從未指定它最初是DllClass的一部分。)

不要忘記在DLL項目中定義BUILDING_DLL,並確保不要在試圖加載DLL的項目中定義它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM