简体   繁体   English

动态链接C ++ DLL…我在做什么错?

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

I've been trying to create a DLL and link the DLL to my program but every time I try my program can't find the function. 我一直在尝试创建一个DLL并将DLL链接到我的程序,但是每次我尝试我的程序都找不到该函数。 The DLL loads fine but the function cant be found. DLL加载正常,但是找不到该函数。

Program: 程序:

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

I'd like to know what I'm doing wrong so I can document it and learn. 我想知道我在做错什么,所以我可以记录下来并学习。

Thanks 谢谢

You need to put your DLL code in an extern "C" block, otherwise the compiler will mangle the names of all functions. 您需要将DLL代码放在extern "C"块中,否则编译器将破坏所有函数的名称

Take a look at this question for further info: C++ DLL Export: Decorated/Mangled names 看看这个问题以获取更多信息: C ++ DLL导出:装饰/拼写的名称

In dll put all functions you want export into 在dll中,将要导出的所有功能放到

    #ifdef __cplusplus
    extern "C" {
    #endif

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

    #ifdef __cplusplus
    } 
    #endif

Function names are mangled when exported, for obvious reasons. 出于明显的原因,函数名称在导出时会被篡改 What if you are using function overloading? 如果使用函数重载怎么办? What if you have a function named hello() in two different classes? 如果您在两个不同的类中都有一个名为hello()的函数,该怎么办? For example, Qt's QString& remove(const QRegExp& rx) is exported as ?remove@QString@@QAEAAV1@ABVQRegExp@@@Z . 例如,Qt的QString& remove(const QRegExp& rx)导出为?remove@QString@@QAEAAV1@ABVQRegExp@@@Z The easiest way to work around this is to export your functions using extern "C" and cdecl or stdcall so they are not mangled (or mangled in a more standard/predictable manner). 解决此问题的最简单方法是使用extern "C"和cdecl或stdcall导出函数,以使它们不被破坏(或以更标准/可预测的方式被破坏)。

You have: 你有:

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

Then you have: 然后您有:

DLLIMPORT void hello()

The combination will turn into this, which doesn't make sense: 组合将变成这样,这没有意义:

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

Change your DLLIMPORT macro to this instead: 将您的DLLIMPORT宏改为:

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

EDIT: You also have dllexport for both cases; 编辑:您也有两种情况下的dllexport; the lower should be dllimport. 较低的应该是dllimport。

You've also used DLLImport rather than DLLIMPORT on the hello method. 您还已经在hello方法上使用了DLLImport而不是DLLIMPORT。

You also cannot (or at least should not) export a non-static class member in a DLL. 您也不能(或至少不应)在DLL中导出非静态类成员。 If you want to export C++ classes I would recommend either: 如果要导出C ++类,我建议:

  1. Export DLL functions which create, destroy and call methods on your class objects. 导出可在类对象上创建,销毁和调用方法的DLL函数。 The creation functions would return something like a HANDLE, void* or similar opaque pointer. 创建函数将返回类似HANDLE,void *或类似的不透明指针的内容。 The other methods would take that as an argument, cast it to what it really is and then call the method on it. 其他方法会将其作为参数,将其强制转换为实际值,然后在其上调用该方法。

  2. Use COM. 使用COM。

You should also follow Sanja Melnichuk's advice to avoid your exported function names being decorated. 您还应该遵循Sanja Melnichuk的建议,以避免修饰导出的函数名称。

Here is an example Dll.h: 这是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);
}

Note that DllClass is gone. 请注意,DllClass已消失。 (Your hello function within dllmain.cpp is unchanged since it never specified it was part of DllClass in the first place.) (您在dllmain.cpp中的hello函数保持不变,因为它从未指定它最初是DllClass的一部分。)

Don't forget to define BUILDING_DLL in the DLL project and ensure you do NOT define it in the project which tries to load the DLL. 不要忘记在DLL项目中定义BUILDING_DLL,并确保不要在试图加载DLL的项目中定义它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM