从不同 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,但适用于任何版本。
在C或C++中,考虑到一个模块可能由多个对象组成,每个对象都应该明确界定。此外,每个对象(.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)
类似(或相关)问题:
我正在尝试包含一些我在 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,但适用于任何版本。
在C或C++中,考虑到一个模块可能由多个对象组成,每个对象都应该明确界定。此外,每个对象(.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)
类似(或相关)问题: