如何在C++程序中使用C头

How do I use C Headers in a C++ Program?

本文关键字:程序 C++      更新时间:2023-10-16

我正在Visual Studio 2010中进行一个项目,该项目将生成一个win 32 dll文件。我的例子是C文件,编译和工作都很好。我想从我写的C++函数中加入一些功能,但我遇到了一些困难。

如果我试图将C++函数链接到C程序,它对字符串等一无所知,而且根本不起作用(当然(。

所以我只能把这个例子改成C++程序,然后我就可以使用我的其他文件而不受惩罚。当我尝试这样做时,我会遇到一个链接错误,我不理解,也不确定如何解决。

示例使用供应商提供的标题,其中包括诸如之类的语句

 typedef void ( __cdecl *BINDING_PROC_BEVNT)(WORD_T choice, INT_T * pStatus, 
            I_EVNT_T  * pIn, O_EVNT_T  * pOut);

在主体代码中,以下是示例:

extern BINDING_PROC_BEVNT       b_evnt;

这样你就可以写了

b_evnt(choice, &status, &inpEvent, &outpEvent);

在供应商提供的C文件中,这些文件再次被引用为:

BINDING_PROC_BEVNT      b_evnt; 
b_evnt = (BINDING_PROC_BEVNT)GetProcAddress(hCNCMod, "bevnt");

我看到的链接器错误是:

错误LNK2001:未解析的外部符号"void(__cdecl*b_evnt

如果我重命名主文件并重新编译为C程序,并省略C++函数,那么一切都会完美编译。即使主文件被处理为C++文件,Intellisense似乎也能识别定义(悬停在上面显示正确的定义(。

此外,我试图将外部"C"添加到几个不同的位置,但在C++文件中似乎没有什么不同,并在C文件中生成了一个编译错误(关于不知道字符串(。

任何见解都将不胜感激,我今天可能只是盯着这个看了太久,没有发现一些明显的东西,也可能是我完全不知道的东西。

谢谢你的帮助!

如果您针对具有C语言绑定的库进行编译,则必须明确告诉C++库的头文件引用的是C对象,而不是C++对象,否则C++名称篡改将阻止正确的链接。通常你可以这样做:

extern "C" {
#include "vendor.h"
}

这将告诉C++编译器,大括号之间的符号是C符号,不应该应用名称篡改。

要包含C++中的C头文件,请执行以下操作:

测试.cpp

extern "C" {
#include "c_header_file.h"
}

听起来上面就是您可能需要做的事情,以便在C++代码中包含供应商头文件。

相关地,使头文件自动为C和C++工作:

c_header_file.h

#ifdef __cplusplus
extern "C" {
#endif
void f(int);
// all declarations go here
#ifdef __cplusplus
}
#endif

并非所有供应商提供的头文件都包含上述__cplusplus检测,因此您必须像第一个示例中那样手动将它们包装在extern "C"中。

error LNK2001: unresolved external symbol "void (__cdecl* b_evnt) 
(unsigned short,short *,union I_EVNT_T *,union O_EVNT_T *)" 
(?b_evnt@@3P6AXGPAFPATI_EVNT_T@@PATO_EVNT_T@@@ZA)

这意味着,找不到C++损坏的变量b_evnt。这是真的,因为它应该是C损坏的(只是一个_前缀(。要解决这个问题,请在为C++进行编译时在头中告诉编译器:

#ifdef __cplusplus
extern "C" BINDING_PROC_BEVNT       b_evnt;
#else
extern BINDING_PROC_BEVNT       b_evnt;
#endif

如果仅此而已,你就完了。如果你需要更多的符号,你可能想使用Greg的解决方案,但要注意,这也不是一个解决方案。

供应商提供的头文件包含在C++编译单元中,但它们不是为C++准备的。因此,函数的声明是用C++编译器支持重载所需的名称篡改来编译的。

标头需要封装在extern "C" {}块中,以便让C++编译器知道这些声明使用了C链接。

可能最简单的方法是使用您自己的包装头来完成以下操作:

#ifndef FOO_WRAPPER_H
#define FOO_WRAPPER_H
#if __cplusplus
extern "C" {
#endif
#include "foo.h"
#if __cplusplus
}
#endif
#endif

并包含yiour包装器头,而不是供应商的头-包装器将适用于C或C++编译。

此外,请联系您的库供应商,让他们知道他们应该进行这些更改——库的用户不应该为了使用C++中的库而采取这种变通方法。