8

根据标题,我正在尝试使用 C 构建一个 DLL 并将其从 C++ 项目链接。我在互联网上阅读并遵循了不同的教程,但每次都缺少一些东西,我不明白是什么。

这是我做的,一步一步:

我创建了一个名为 的新 Win32 项目,testlib然后,从向导中,我选择了“DLL”和“空项目”。

添加了一个标题:

//testlib.h

#include <stdio.h>

__declspec(dllexport) void hello();

添加了一个来源;因为我希望它是我阅读的 C 源代码,所以我应该简单地重命名 .c 中的 .cpp 文件,所以

//testlib.c

#include "testlib.h"

void hello() {
    printf("DLL hello() called\n");
}

构建成功。

现在我想在另一个项目中使用我有用的 dll。

然后:新项目(testlibUse)。这次我选择了“空项目”。
无需添加header,创建一个cpp源即可

//main.cpp
#include <testlib.h>

int main() {
    hello();
}

然后:

  • 我将路径添加到testlib.dll属性-> VC++ 目录-> 可执行目录中的文件夹

  • 我将路径添加到testlib.h属性-> VC++ 目录-> 包含目录中的文件夹

  • testlib.lib我在属性->链接器->输入->附加依赖项中添加了(包含的扩展名)的路径

我尝试构建,但出现链接器错误:

LINK : C:\path\testlibUse\Debug\testlibUse.exe 未找到或不是由最后一个增量链接构建的;执行完整链接
main.obj:错误 LNK2019:无法解析的外部符号“void __cdecl hello(void)”(?hello@@YAXXZ) 在函数 _main
C:\path\testlibUse\Debug\testlibUse.exe 中引用:致命错误 LNK1120:1未解决的外部

如果我回到,testlib重新命名并重新构建 dll,那么我可以构建,但在运行时出现“找不到 dll”错误。testlib.ctestlib.cpptestlibUse

我还尝试在“发布”中更改两个项目的配置(在需要的地方更改路径),但没有任何改变。

很抱歉这篇文章很长,但我认为有必要准确地写下我所做的。

有什么建议么?

此外,如果我想在 Qt 项目中使用我的 dll,是否需要更改任何配置参数?

4

4 回答 4

11

你有几个问题:

  1. 头文件应将函数标记为在 DLL 中编译时导出但在库用户编译时导入。
  2. 头文件应在编译为 C++ 时将函数声明包装在一个extern "C"块中,以确保名称不会被破坏
  3. DLL 不在可执行文件的库搜索路径中,因此在运行时无法找到。

要修复 (1) 和 (2),请像这样重写标题:

#ifdef __cplusplus
extern "C" {
#endif

// Assume this symbol is only defined by your DLL project, so we can either
// export or import the symbols as appropriate
#if COMPILING_MY_TEST_DLL
#define TESTLIB_EXPORT __declspec(dllexport)
#else
#define TESTLIB_EXPORT __declspec(dllimport)
#endif

TESTLIB_EXPORT void hello();
// ... more function declarations, marked with TESTLIB_EXPORT

#ifdef __cplusplus
}
#endif

要修复 (3),请将 DLL 复制到与可执行文件相同的文件夹中。您设置的“可执行目录”设置不会影响 DLL 搜索——有关如何搜索 DLL 的详细说明,请参阅MSDN 。对您来说最好的解决方案是将 DLL 复制到可执行文件所在的目录中。您可以手动执行此操作,也可以将构建后步骤添加到为您执行此操作的项目中。

于 2012-05-02T17:26:27.203 回答
3

你应该extern "C"包括:

extern "C" {
    #include <testlib.h>
}
于 2012-05-02T17:09:53.940 回答
1

看起来您似乎需要确保编译器不会破坏cpp 构建中的符号名称。您应该能够extern "C"在 testlib.h 中的定义中添加一个:

#ifdef __cplusplus
extern "C"
#endif
__declspec(dllexport) void hello();
于 2012-05-02T17:09:33.170 回答
1

这是 C++ 可以包含的 C 头文件的方法。确保TESTLIB_EXPORTS仅在您的DLL预处理器设置中进行设置。在包含此头文件以使用 DLL 的项目中,头文件会将函数声明为导入而不是导出。

守卫将__cplusplus告诉编译器使用 C 名称修饰而不是 C++ 名称修饰来导入您的函数。

#include <stdio.h>

#ifdef TESTLIB_EXPORTS
#define TESTLIB_API __declspec(dllexport)
#else
#define TESTLIB_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

TESTLIB_API void hello();
/* other prototypes here */

#ifdef __cplusplus
}
#endif
于 2012-05-02T17:26:46.097 回答