使用 C++ Dll 的 LNK2019 构造函数/析构函数

Posted

技术标签:

【中文标题】使用 C++ Dll 的 LNK2019 构造函数/析构函数【英文标题】:LNK2019 constructor/destructor using C++ Dll 【发布时间】:2018-03-01 08:42:14 【问题描述】:

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

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

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

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

DLL = Projet / Test = 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 上,我选择测试项目作为启动项目以获取信息。我看了很多关于 SO 的帖子,但我现在没有找到解决方案。提前谢谢你。

【问题讨论】:

错误消息中引用的符号与您代码中的任何符号都不匹配。这段代码要么不完整,要么是假的。无论哪种方式,通过提供minimal reproducible example 来修复它。 【参考方案1】:

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

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

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

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

【讨论】:

谢谢,我现在定义了我的班级class __declspec(dllexport) Projet,它正在工作。我必须将我的 DLL 发送给我的同事,以确保他现在可以用 C# 读取它。【参考方案2】:

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

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

class Projet;
typedef Projet* PProjet;

然后使用 PProject 作为不透明句柄。

您还需要像这样导出 Projet 类:

class EXPORT Projet

能够由客户端实例化该类或添加返回引用的工厂函数。

【讨论】:

抱歉,我为我的帖子更改了一些变量的名称,忘记了对应于ProjetEpsCndCoreDll。在我的类的定义中添加__declspec(dllexport) 解决问题;) 使用硬编码的 __declspec(dllexport) 会破坏客户端导入类的优化。使用您之前创建的 EXPORT 宏。【参考方案3】:

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

【讨论】:

“将 DLL 引用添加到 DLL” 在本机应用程序中没有任何意义。本机应用程序使用导入库来解析符号。

以上是关于使用 C++ Dll 的 LNK2019 构造函数/析构函数的主要内容,如果未能解决你的问题,请参考以下文章

编译dll但出现错误LNK2019

“error LNK2019: 无法解析的外部符号”之分析

无法链接 GLFW C++;添加了 .dll、.h、.lib,但仍然获得 LNK2019

LNK2019“未解析的外部符号”错误(C++ OpenGL)

LNK2019:未解析的外部符号——隐式 DLL [重复]

带有 QGraphicsView 子类的构造函数上的 LNK2019