I'm trying to build a C++ program with borland C++ Builder V5.5. Everything works fine until I tryed to call a function defined in a c file. The compiler works finde but linking is not working. The linker is not able to find the function called from c++ file. The .obj file is gernerated and part of the project xml file. Do anybody now how I can solve this error. To be sure that there are no side effects, I start a new project just calling c function call in constructor. The Project structure looks the following:
我正在尝试使用borland C ++ Builder V5.5构建一个C ++程序。在我尝试调用c文件中定义的函数之前,一切正常。编译器工作finde但链接不起作用。链接器无法找到从c ++文件调用的函数。 .obj文件是gernerated并且是项目xml文件的一部分。现在有人如何解决这个错误。为了确保没有副作用,我启动一个新项目,只是在构造函数中调用c函数调用。 Project结构如下所示:
Form1.h defines Constructor and includes header where the c function is defined
Form1.h定义了构造函数,并包含定义c函数的头文件
Form1.cpp implements Constructor and call the c function
Form1.cpp实现了Constructor并调用了c函数
test.h defines an void function "void abc();"
test.h定义了一个void函数“void abc();”
test.c includes test.h and implements an void function "void abc() {}"
test.c包含test.h并实现void函数“void abc(){}”
Unresolved external "abc()" referenced from ...unit1.obj
从... unit1.obj引用的未解析的外部“abc()”
Do anyone have an idea??
有没有人有想法?
Here some code
这里有一些代码
#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()
{
}
3 个解决方案
#1
1
See C++ FAQ Item [32.4] How can I modify my own C header files so it's easier to #include them in C++ code. (Read the whole of section 32 actually.). Use:
请参阅C ++ FAQ项目[32.4]如何修改自己的C头文件,以便在C ++代码中更容易#include它们。 (实际上阅读第32节的全部内容。)。使用:
#ifndef RTW_HEADER_Multicopter_Model_h_
#define RTW_HEADER_Multicopter_Model_h_
#ifdef __cplusplus
extern "C" {
#endif
void abcdefg();
#ifdef __cplusplus
}
#endif
#endif */
#2
3
I don't know anything about Borland C++ specifically, but if you're declaring something in C++ code that was built as C you typically need to put extern "C" { ... }
around the declaration. So, in this case, your Multicopter_Model.h
file would want to say something like this:
我对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
The reason for this is that in order to support features such as overloading, an object file built from C++ code has something called name mangling applied to it, whereby (e.g.) a function foo
that takes an int
and returns an int
might actually be called something like foo__Rint_Aint
to encode that information. (Note 1: Real name mangling conventions are more concise and cryptic. Note 2: In theory the same could be achieved by means other than name mangling, but in practice everyone does name mangling. Note 3: Different compilers do different forms of name mangling.) So when the C++ compiler sees the declaration of abcdefg
without the magic annotation to tell it "this is really C, not C++", the name gets mangled and the compiled code actually expects to find a function called (in my made-up name-mangling convention) abcdefg_Rvoid_Anone
or something. That function doesn't exist because the C compiler that built Form1.obj
doesn't do C++ name-mangling, so the linker can't find what it's looking for.
这样做的原因是,为了支持诸如重载之类的功能,从C ++代码构建的目标文件有一个名为mangling的东西应用于它,其中(例如)一个接受int并返回一个int的函数foo实际上可能被调用类似于foo__Rint_Aint来编码该信息。 (注1:实名修改惯例更简洁,更神秘。注2:理论上可以通过名称修改以外的方式实现同样的功能,但实际上每个人都会命名为修改。注3:不同的编译器会执行不同形式的名称修改。)因此,当C ++编译器看到没有魔术注释的abcdefg声明告诉它“这真的是C,而不是C ++”时,名称会被破坏,编译的代码实际上希望找到一个叫做的函数(在我的化妆中)名称修改惯例)abcdefg_Rvoid_Anone等等。该函数不存在,因为构建Form1.obj的C编译器不执行C ++名称修改,因此链接器无法找到它正在查找的内容。
There's a bit of a clue hidden in the linker's error message. You'll notice that it says it couldn't find abcdefg()
rather than just abcdefg
. That's because the argument list is encoded into the name it's looking for. The linker is kindly reporting a human-readable version of the name rather than whatever mangled monstrosity it was actually looking for.
链接器的错误消息中隐藏着一些线索。你会注意到它说它找不到abcdefg()而不仅仅是abcdefg。那是因为参数列表被编码为它正在寻找的名称。链接器正在报告一个人类可读的名称版本,而不是它实际上正在寻找的任何受损的怪物。
#3
0
For function overloading and overriding to work in C++, all C++ compilers adds information to the function name (see http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B). C doesn't, so when you have a prototype in C++ the generated symbol name will not be the same as the one generated by a C compiler.
对于函数重载和覆盖在C ++中工作,所有C ++编译器都会向函数名称添加信息(请参阅http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B)。 C没有,因此当您在C ++中使用原型时,生成的符号名称将与C编译器生成的符号名称不同。
See the other answers on how to fix this.
请参阅有关如何解决此问题的其他答案。
#1
1
See C++ FAQ Item [32.4] How can I modify my own C header files so it's easier to #include them in C++ code. (Read the whole of section 32 actually.). Use:
请参阅C ++ FAQ项目[32.4]如何修改自己的C头文件,以便在C ++代码中更容易#include它们。 (实际上阅读第32节的全部内容。)。使用:
#ifndef RTW_HEADER_Multicopter_Model_h_
#define RTW_HEADER_Multicopter_Model_h_
#ifdef __cplusplus
extern "C" {
#endif
void abcdefg();
#ifdef __cplusplus
}
#endif
#endif */
#2
3
I don't know anything about Borland C++ specifically, but if you're declaring something in C++ code that was built as C you typically need to put extern "C" { ... }
around the declaration. So, in this case, your Multicopter_Model.h
file would want to say something like this:
我对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
The reason for this is that in order to support features such as overloading, an object file built from C++ code has something called name mangling applied to it, whereby (e.g.) a function foo
that takes an int
and returns an int
might actually be called something like foo__Rint_Aint
to encode that information. (Note 1: Real name mangling conventions are more concise and cryptic. Note 2: In theory the same could be achieved by means other than name mangling, but in practice everyone does name mangling. Note 3: Different compilers do different forms of name mangling.) So when the C++ compiler sees the declaration of abcdefg
without the magic annotation to tell it "this is really C, not C++", the name gets mangled and the compiled code actually expects to find a function called (in my made-up name-mangling convention) abcdefg_Rvoid_Anone
or something. That function doesn't exist because the C compiler that built Form1.obj
doesn't do C++ name-mangling, so the linker can't find what it's looking for.
这样做的原因是,为了支持诸如重载之类的功能,从C ++代码构建的目标文件有一个名为mangling的东西应用于它,其中(例如)一个接受int并返回一个int的函数foo实际上可能被调用类似于foo__Rint_Aint来编码该信息。 (注1:实名修改惯例更简洁,更神秘。注2:理论上可以通过名称修改以外的方式实现同样的功能,但实际上每个人都会命名为修改。注3:不同的编译器会执行不同形式的名称修改。)因此,当C ++编译器看到没有魔术注释的abcdefg声明告诉它“这真的是C,而不是C ++”时,名称会被破坏,编译的代码实际上希望找到一个叫做的函数(在我的化妆中)名称修改惯例)abcdefg_Rvoid_Anone等等。该函数不存在,因为构建Form1.obj的C编译器不执行C ++名称修改,因此链接器无法找到它正在查找的内容。
There's a bit of a clue hidden in the linker's error message. You'll notice that it says it couldn't find abcdefg()
rather than just abcdefg
. That's because the argument list is encoded into the name it's looking for. The linker is kindly reporting a human-readable version of the name rather than whatever mangled monstrosity it was actually looking for.
链接器的错误消息中隐藏着一些线索。你会注意到它说它找不到abcdefg()而不仅仅是abcdefg。那是因为参数列表被编码为它正在寻找的名称。链接器正在报告一个人类可读的名称版本,而不是它实际上正在寻找的任何受损的怪物。
#3
0
For function overloading and overriding to work in C++, all C++ compilers adds information to the function name (see http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B). C doesn't, so when you have a prototype in C++ the generated symbol name will not be the same as the one generated by a C compiler.
对于函数重载和覆盖在C ++中工作,所有C ++编译器都会向函数名称添加信息(请参阅http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B)。 C没有,因此当您在C ++中使用原型时,生成的符号名称将与C编译器生成的符号名称不同。
See the other answers on how to fix this.
请参阅有关如何解决此问题的其他答案。