动态链接C ++ DLL ...我做错了什么?

时间:2010-11-28 11:05:26

标签: c++

我一直在尝试创建一个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.h

#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_ */

我想知道我做错了什么,所以我可以记录并学习。

由于

4 个答案:

答案 0 :(得分:1)

您需要将DLL代码放在extern "C"块中,否则编译器将mangle the names所有函数。

请查看此问题以获取更多信息: C++ DLL Export: Decorated/Mangled names

答案 1 :(得分:0)

在dll中将您要导出的所有功能放入

    #ifdef __cplusplus
    extern "C" {
    #endif

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

    #ifdef __cplusplus
    } 
    #endif

答案 2 :(得分:0)

导出时的函数名are mangled,原因很明显。如果您正在使用函数重载怎么办?如果在两个不同的类中有一个名为hello()的函数,该怎么办?例如,Qt的QString& remove(const QRegExp& rx)导出为?remove@QString@@QAEAAV1@ABVQRegExp@@@Z。解决这个问题的最简单方法是使用extern "C"和cdecl或stdcall导出函数,这样它们就不会被破坏(或以更标准/可预测的方式破坏)。

答案 3 :(得分:0)

你有:

#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。

  3. 您还应该遵循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的项目中定义它。