从不同 VS2010 项目中的 C++ 代码调用 C 函数时出现链接器错误

Linker error when calling a C function from C++ code in different VS2010 project

我正在尝试包含一些我在 C++ 项目中找到的 C 代码。该函数在 C 文件中是这样定义的。

#ifdef __cplusplus
extern "C" {
#endif
 extern char *dtoa(double, int, int, int *, int *, char **);
 extern char *g_fmt(char *, double);
 extern void freedtoa(char*);
#ifdef __cplusplus
    }
#endif

 char *
g_fmt(register char *b, double x)
{

我将其包含在其中的 VS 项目正在创建一个 dll。该文件被编译为 C,项目中的其他文件被编译为 C++。

我添加了一个 header 以包含在我的 C++ 文件中

#ifndef G_FMT_H
#define G_FMT_H
#ifdef __cplusplus
extern "C" {
#endif
 extern char *dtoa(double, int, int, int *, int *, char **);
 extern char *g_fmt(char *, double);
 extern void freedtoa(char*);

#ifdef __cplusplus
}
#endif
#endif //G_FMT_H

在解决方案的另一个项目中,我包含了我的 header 并尝试调用 g_fmt 函数。

#include "header.h"
...
g_fmt(my_array, 2.0);

这个项目正在 link 连接到另一个项目,我可以毫无问题地调用第一个库中的 C++ 函数。但是,添加上面的行会给我一个 lnk2001 错误。

error LNK2001: unresolved external symbol g_fmt

我发现了一些关于混合使用 C 和 C++ 的其他问题,我似乎已经在正确的位置使用 extern 关键字完成了所有必要的工作,但是我仍然无法 link。我需要在 VS2010 中做些什么吗?

问题针对 VStudio 2010,但适用于任何版本

CC++中,考虑到一个模块可能由多个对象组成,每个对象都应该明确界定。此外,每个对象(.c.cpp 文件)都应该有自己的头文件。因此,对于 C 函数,您应该有一个头文件和一个 .c(xx) 文件 (3 在你的例子中)。
此外,作为一般准则,命名文件和宏时尽量保持一致:您的 header.h 文件使用 G_FMT_H 包含守卫的宏。
尝试将您的 .h.c 文件重组为:

functions.h:

#pragma once

#if defined(_WIN32)
#  if defined(FUNCTIONS_STATIC)
#    define FUNCTIONS_API
#  else
#    if defined(FUNCTIONS_EXPORTS)
#      define FUNCTIONS_API __declspec(dllexport)
#    else
#      define FUNCTIONS_API __declspec(dllimport)
#    endif
#  endif
#else
#  define FUNCTIONS_API
#endif

#if defined(__cplusplus)
extern "C" {
#endif

    FUNCTIONS_API char *dtoa(double, int, int, int*, int*, char**);
    FUNCTIONS_API char *g_fmt(char*, double);
    FUNCTIONS_API void freedtoa(char*);

#if defined(__cplusplus)
}
#endif

和对应的实现(functions.c):

#define FUNCTIONS_EXPORTS
#include "functions.h"


char *dtoa(double, int, int, int*, int*, char**) {
    //function statements
}


char *g_fmt(char*, double) {
    //function statements
}


void freedtoa(char*) {
    //function statements
}

头文件中有 2 点需要注意(除了重组和重命名):

  • 每个函数的 extern 存储说明符消失了
  • 导出逻辑:您的项目现在将定义 FUNCTIONS_EXPORT(来自 functions.c,或 desirable 成为 VStudio 项目设置 - 无论如何,before #include "functions.h")
    • 当这个项目(functions.c)被编译时,函数将被导出(由于宏定义)
    • 当头文件将包含在另一个项目中(没有定义 FUNCTIONS_EXPORTS)时,函数将被标记为已导入,并且链接器将在导入的 .lib(s) 中搜索它们 - 其中之一应该是由该项目生成的
    • 为了更严格,您可以替换 FUNCTIONS_EXPORTS(并从 functions.c[=77= 中删除它的定义]) 由 自动 定义的宏 VStudio IDE: ${YOUR_PROJECT_NAME}_EXPORTS (例如,如果您的 Dll 项目名为 ExportFunctionsProject.vc(x)proj,则宏名称将为 EXPORTFUNCTIONSPROJECT_EXPORTS)
    • 您可以在VStudio (2010) IDE中查看宏名称:Project Properties -> C/C++ ->预处理器 -> 预处理器定义。有关详细信息,请查看 [MS.Docs]: /D (Preprocessor Definitions)

类似(或相关)问题: