在C中创建一个DLL并从C ++项目链接它

时间:2012-05-02 17:03:02

标签: c++ c dll linker

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

这就是我一步一步做的事情:

我创建了一个名为testlib的新Win32项目,然后,从向导中选择“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)。这次我选择了“空项目”。
无需添加标题,只需创建一个cpp源

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

int main() {
    hello();
}

然后:

  • 我在Properties-&gt; VC ++目录 - &gt;可执行目录

  • 中添加了testlib.dll文件夹的路径
  • 我在“属性 - &gt; VC ++目录 - &gt;包含目录

  • 中添加了testlib.h文件夹的路径
  • 我在“属性” - >“链接器” - >“输入 - &gt;附加依赖项

  • 中添加了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个未解析的外部

如果我回到testlib,请在testlib.c中重新命名testlib.cpp并重建dll,然后我就可以构建testlibUse但我得到了“dll not发现“运行时出错。

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

对于长篇文章感到抱歉,但我认为有必要写下我的确切内容。

有什么建议吗?

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

4 个答案:

答案 0 :(得分:10)

你有几个问题:

  1. 头文件应将函数标记为在DLL中编译时导出,但在库用户编译时导入。
  2. 当编译为C ++时,头文件应将函数声明包装在extern "C"块中,以确保名称不会被破坏
  3. DLL不在您的可执行文件库搜索路径中,因此在运行时无法找到它。
  4. 要修复(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复制到可执行文件所在的目录中。您可以手动执行此操作,也可以为项目添加生成后步骤,以便为您执行此操作。

答案 1 :(得分:3)

您应该extern "C"包含:

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

这是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