【问题标题】:Create a DLL in C and link it from a C++ project在 C 中创建一个 DLL 并从 C++ 项目中链接它
【发布时间】:2012-05-12 04:51:08
【问题描述】:

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

这是我做的,一步一步:

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

添加了标题:

//testlib.h

#include <stdio.h>

__declspec(dllexport) void hello();

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

//testlib.c

#include "testlib.h"

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

构建成功。

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

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

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

int main() {
    hello();
}

然后:

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

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

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

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

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

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

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

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

有什么建议吗?

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

【问题讨论】:

    标签: c++ c dll linker


    【解决方案1】:

    你有几个问题:

    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 复制到可执行文件所在的目录中。您可以手动执行此操作,也可以为您的项目添加一个构建后步骤来为您执行此操作。

    【讨论】:

    • 我想补充一点,值得一提的是,大多数 C++ 编译器会自动定义 __cplusplus 宏。
    • @MohammedNoureldin:所有 C++ 编译器在编译 C++ 代码时会自动定义 __cplusplus 宏。自 1998 年以来的所有 C++ 标准都要求它。
    【解决方案2】:

    您应该extern "C" 包括:

    extern "C" {
        #include <testlib.h>
    }
    

    【讨论】:

    • 构建成功,但在运行时出现“找不到 dll”错误...在 Properties->VC++ 目录->可执行目录中添加 dll 的路径还不够吗?
    【解决方案3】:

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

    #ifdef __cplusplus
    extern "C"
    #endif
    __declspec(dllexport) void hello();
    

    【讨论】:

    • 构建成功,但在运行时出现“找不到 dll”错误...在 Properties->VC++ 目录->可执行目录中添加 dll 的路径还不够吗?
    • @Saphrosit:不,据我所知,这不会影响应用程序的运行。阅读该属性页上的描述;它会在构建项目时影响二进制文件的查找。您需要在运行时找到 DLL(例如,通过 PATH 环境变量)。
    【解决方案4】:

    这是 C++ 可以包含的 C 头文件的方法。确保仅在您的 DLL 预处理器设置中设置TESTLIB_EXPORTS。在包含此头文件以使用 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多