LNK2019 constructor/destructor 使用 C++ Dll

LNK2019 constructor/destructor using C++ Dll

我正在开发一个带有 C 包装器的 C++ DLL,以便在 Python 和 C# 中使用它。所以我在 Visual Studio 上创建了一个项目 (DLL) 来开发和编译它。这里没问题。我什至可以在 Python 上毫无问题地使用我的 DLL。

但是,在 Visual 上,我想在与 DLL 相同的解决方案中创建另一个项目来测试 DLL。

所以我创建了第二个项目(Win32 Windows 应用程序),将 .h 添加到头文件,将 link 添加到 .lib文件我在测试项目的文件夹中添加,但是当我尝试编译它时,我有关于LNK2019的错误,以构造函数开头:

error LNK2019: unresolved external symbol "public: __cdecl Projet::Projet(void)" (??Projet@@QEAA@XZ) referenced in function main

DLL = Projet / 测试 = Projet_Test

Projet.h

#pragma once
#include "Projet_inc.h"

class Projet
{
public:
    Projet();
    ~Projet();

    int multiply(int arg1, int arg2);
    int result;
};

Projet_inc.h

#ifdef PROJET_EXPORTS
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT __declspec(dllimport)
#endif

#define CALLCONV_API __stdcall

#ifdef __cplusplus
extern "C" // C wrapper
{
#endif

    typedef struct Projet Projet; // make the class opaque to the wrapper

    EXPORT Projet* CALLCONV_API cCreateObject(void);
    EXPORT int CALLCONV_API cMultiply(Projet* pDLLobject, int arg1, int arg2);
#ifdef __cplusplus
}
#endif

Projet.cpp

#include "stdafx.h"
#include "Projet.h"

Projet::Projet() {}
Projet::~Projet() {}

int Projet::multiply(int arg1, int arg2) {
    result = arg1 * arg2;
    return result;
}

Projet* EXPORT CALLCONV_API  cCreateObject(void)
{
    return new Projet();
}

int EXPORT CALLCONV_API  cMultiply(Projet* pDLLtest, int arg1, int arg2)
{
    if (!pDLLtest)
        return 0;
    return pDLLtest->multiply(arg1, arg2);
}

Projet_Test.cpp

// Projet_Test.cpp : définit le point d'entrée pour l'application console.
//

#include "stdafx.h"
#include "Projet.h"

int main()
{
    Projet object;
    return 0;
}

在 Visual 上,我 select 将测试项目作为启动项目以供参考。我看了很多关于 SO 的帖子,但我暂时没有找到解决方案。提前谢谢你。

确保您已将 DLL 引用添加到您的 DLL。

您需要 __declspec(dllexport) 所有 您想直接调用的函数,而不仅仅是 C 函数。

在您的示例中,您应该能够正确调用 C 包装函数 cCreateObjectcMultiply,因为它们已正确导出,但您将无法调用底层 C++ 函数像 Projet::Projet()Projet::~Projet().

您有两种解决方法:您可以将这些函数更改为内联函数并将它们的实现移至 header。这样,客户端项目将不再为这些函数调用 DLL 中的代码,而是直接自己编译内联定义。一般来说,这显然不是一个明智的做法。或者,用 __declspec(dllexport) 标记您的 C++ 成员函数,就像您对 C 函数所做的那样。

注意Visual Studio有破坏版本间C++ ABI的倾向,所以你需要确保你用来编译dll的编译器版本与你用来编译客户端的编译器版本兼容应用。如果两个部分都使用相同的 Visual Studio 版本编译,或者如果您坚持使用纯 C 接口,这不是问题。

首先,关于缺少符号 EpsCndCoreDll 的错误似乎与这里的上下文无关,您应该得到关于将结构重新定义为 class (class Projet) 的编译错误。

可能你需要使用类似的东西:

class Projet;
typedef Projet* PProjet;

并进一步使用 PProject 作为不透明句柄。

您还需要导出 Projet class 如:

class EXPORT Projet

能够由客户端实例化 class 或添加 returns 引用的工厂函数。