C++ Visual Studio Windows:如何在 dll 中声明但不定义外部函数

Posted

技术标签:

【中文标题】C++ Visual Studio Windows:如何在 dll 中声明但不定义外部函数【英文标题】:C++ Visual Studio Windows: how to declare but not define extern function in dll 【发布时间】:2020-10-14 19:28:01 【问题描述】:

我有一个项目编译成库,并声明了某个函数要由库的用户实现:

//To be defined by user
Application* CreateApplication();

在 Linux 上将代码编译到共享库中时,它可以完美运行。库的任何用户都可以为声明的函数定义一个实现,并且可以在库中使用它。如果库的用户忘记定义一个实现,他们会得到一个错误指出这一点。

我现在正在将库移植到 Windows,它应该被编译成 dll。但是,由于 Visual Studio 使用的链接器在抱怨,我遇到了问题:

unresolved external symbol Application* __cdecl CreateApplication(void)

我尝试添加 extern 关键字来表明函数的定义在其他地方,但这不起作用。

为什么我不能像这样在 dll 中声明(但不定义)函数?我应该如何修复我的代码,使其在 Linux 和 Windows 上都能正常工作?

【问题讨论】:

如果您在 Linux 中这样做并在共享库上使用 dlopen + dlsym,除非您之前已加载用户的库,否则您将收到运行时错误。 "函数dlsym() 接受由dlopen(3) 返回的动态加载共享对象的“句柄”以及以空结尾的符号名称,并返回该符号被加载到内存中的地址。如果符号是未找到,在指定对象或由dlopen(3) 在加载该对象时自动加载的任何共享对象中,dlsym() 返回NULL" 我正在同一个项目中编译库的用户。也许这就是它起作用的原因?也许问题应该是我应该如何在 Windows 和 Linux 中做到这一点? 是的,这听起来很脆弱。 对我应该如何处理这个问题有什么建议吗?将其设为静态库会解决问题吗? .... 或按照 Remy 的建议进行操作 :-) 【参考方案1】:

你试图做的只能在静态库中工作,它不能在像 DLL 这样的动态库中工作。为此,您必须更改代码以改用函数指针。使用 DLL 的应用程序可以从自己的代码中传递所需函数的地址,然后 DLL 可以将该地址分配给它根据需要使用的变量,例如:

标题:

#ifndef MYLIB_H
#ifndef MYLIB_H

#ifdef COMPILING_MY_LIB
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT __declspec(dllimport)
#endif

// declare Application as needed...

typedef Application (*lpCreateApplicationFunc)();

#ifdef __cplusplus
extern "C" 
#endif

MY_EXPORT void SetCreateApplicationFunc(lpCreateApplicationFunc func);

#ifdef __cplusplus

#endif

#endif

DLL:

#define COMPILING_MY_LIB
#include "MyLib.h"

//To be defined by user
lpCreateApplicationFunc CreateApplication = NULL;

void SetCreateApplicationFunc(lpCreateApplicationFunc func)

    CreateApplication = func;


void doSomething()

    Application *app = NULL;

    if (CreateApplication)
        app = (*CreateApplication)();

    if (app)
    
        ...
    

EXE:

#include "MyLib.h"

Application MyCreateApplicationFunc()

    ...


// during startup, call this...
SetCreateApplicationFunc(&MyCreateApplicationFunc);

【讨论】:

以上是关于C++ Visual Studio Windows:如何在 dll 中声明但不定义外部函数的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Windows 桌面 (C++) 打开 Visual Studio Express 2013? [关闭]

将 C++ Win32 控制台项目类集成到 Visual Studio 2008 中的 Visual C++(Windows 窗体应用程序)项目中

如何在 Visual Studio 2017 中创建 C++ Windows 桌面应用程序?

在 Windows 上安装 OpenCV 并使用 Visual Studio C++ 构建程序

无法在 Visual Studio 中将 Visual C++ 运行时包引用添加到 Windows Phone 项目

Windows 下 Visual Studio 2012 / Intel 编译器的 C++ 双精度失败