2

我正在尝试使用 borland C++ Builder V5.5 构建一个 C++ 程序。一切正常,直到我尝试调用 ac 文件中定义的函数。编译器可以找到但链接不起作用。链接器无法找到从 c++ 文件调用的函数。.obj 文件被生成并且是项目 xml 文件的一部分。现在做任何人我如何解决这个错误。为了确保没有副作用,我开始了一个新项目,只是在构造函数中调用 c 函数调用。项目结构如下所示:

Form1.h 定义 Constructor 并包含定义 c 函数的标头

Form1.cpp实现Constructor并调用c函数

test.h 定义了一个 void 函数“void abc();”

test.c 包含 test.h 并实现了一个 void 函数“void abc() {}”

从 ...unit1.obj 引用的未解析的外部“abc()”

有人有想法吗?

这里有一些代码

#include <vcl.h>
#pragma hdrstop
#include "Multicopter_Model.h"
#include "Unit1.h"

#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
abcdefg();
return;
}

_

#ifndef RTW_HEADER_Multicopter_Model_h_
#define RTW_HEADER_Multicopter_Model_h_

void abcdefg();

#endif */

_

#include "Multicopter_Model.h"
/* Model initialize function */
void abcdefg()
{

}
4

3 回答 3

3

我对 Borland C++ 一无所知,但如果您在 C++ 代码中声明某些内容,并且该代码是作为 C 构建的,那么您通常需要extern "C" { ... }在声明周围加上。因此,在这种情况下,您的Multicopter_Model.h文件会想说这样的话:

#ifndef RTW_HEADER_Multicopter_Model_h_
#define RTW_HEADER_Multicopter_Model_h_

#ifdef __cplusplus
extern "C" {
#endif

void abcdefg();

#ifdef __cplusplus
}
#endif

#endif

这样做的原因是,为了支持诸如重载之类的特性,从 C++ 代码构建的目标文件应用了一个名为name mangling的东西,因此(例如)一个foo接受 anint并返回 an的函数int实际上可能被称为foo__Rint_Aint类似编码该信息。(注 1:实名修改约定更加简洁和神秘。注 2:理论上可以通过名称修改以外的方式实现相同的目的,但实际上每个人都会进行名称修改。注 3:不同的编译器执行不同形式的名称修改.) 所以当 C++ 编译器看到abcdefg如果没有神奇的注释告诉它“这真的是 C,而不是 C++”,名称就会被破坏,编译后的代码实际上希望找到一个名为(在我编造的名称修改约定中)abcdefg_Rvoid_Anone或其他东西的函数。该函数不存在,因为构建的 C 编译器Form1.obj不执行 C++ 名称修改,因此链接器无法找到它要查找的内容。

链接器的错误消息中隐藏着一些线索。你会注意到它说它找不到abcdefg(),而不仅仅是abcdefg. 那是因为参数列表被编码成它正在寻找的名称。链接器友好地报告名称的人类可读版本,而不是它实际寻找的任何损坏的怪物。

于 2012-06-14T08:11:31.587 回答
1

请参阅 C++ FAQ Item [32.4] How can I modify my own C header files so that it's more easier to #include them in C++ code。(实际上阅读第 32 节的全部内容。)。利用:

#ifndef RTW_HEADER_Multicopter_Model_h_
#define RTW_HEADER_Multicopter_Model_h_

#ifdef __cplusplus
 extern "C" {
#endif 

void abcdefg();

#ifdef __cplusplus
 }
#endif 
#endif */
于 2012-06-14T08:11:25.207 回答
0

对于在 C++ 中工作的函数重载和覆盖,所有 C++ 编译器都会在函数名称中添加信息(参见http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B)。C 没有,因此当您在 C++ 中有原型时,生成的符号名称将与 C 编译器生成的符号名称不同。

请参阅有关如何解决此问题的其他答案。

于 2012-06-14T08:14:18.397 回答