从不同的VS2010项目中的C ++代码调用C函数时出现链接器错误
我正在尝试包含我在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 ++。
我添加了一个标题以包含在我的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
在解决方案的另一个项目中,我包含我的标题并尝试调用g_fmt函数。
#include "header.h" ... g_fmt(my_array, 2.0);
这个项目链接到另一个,我能够在第一个库中调用C ++函数而没有任何问题。 但是,添加上面的行会给我一个lnk2001错误。
error LNK2001: unresolved external symbol g_fmt
我发现了一些关于混合使用C和C ++的其他问题,我似乎已经在正确的位置使用extern关键字做了所有必要的事情,但是我仍然无法链接。 在VS2010中我需要做些什么吗?
在C或C ++中 ,考虑到模块可能由多个对象组成,每个对象都应该清楚地分隔。 此外,每个对象( .c或.cpp文件)都应该有自己的头文件。 因此,您应该有一个头文件和一个c(xx)文件用于C函数(在您的示例中为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 }
在头文件中需要注意的两件事(除了重新组织和重命名):
- 每个函数的
extern
存储说明符都消失了 - 导出逻辑:你的项目现在将定义
FUNCTIONS_EXPORT
(来自functions.c ,或者希望是一个VStudio项目设置 – 无论如何, 在#include "functions.h"
之前的某个地方#include "functions.h"
)- 当编译这个项目( functions.c )时,将导出函数(由于宏定义)
- 当头文件将包含在另一个项目中(没有定义
FUNCTIONS_EXPORTS
)时,函数将被标记为已导入,链接器将在导入的库中搜索它们 – 其中一个应该是生成的一个通过这个项目 - 为了更加严格,您可以通过VStudio IDE 自动
#define
d替换FUNCTIONS_EXPORTS
(并从functions.c中删除它的定义):${YOUR_PROJECT_NAME}_EXPORTS
(例如,如果您的Dll项目名为ExportFunctionsProject.vc(x) )proj ,然后宏名称将是EXPORTFUNCTIONSPROJECT_EXPORTS
) - 您可以在VStudio(2010)IDE中检查宏名称: 项目属性 – > C / C ++ – >预处理器 – >预处理器定义 。 有关更多详细信息,请查看[MSDN]:/ D(预处理器定义)
类似(或相关)问题:
- [SO]:Excel VBA,无法从DLL文件中找到DLL入口点(@CristiFati的回答)
- [SO]:CLR Windows窗体中的LNK2005错误(@ CristiFati的回答)
EDIT0 :为静态构建添加了“支持” 。
编辑1 :跨平台+一些更正。