Borland C++ linker error c file include
-
14-06-2021 - |
Question
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:
Form1.h defines Constructor and includes header where the c function is defined
Form1.cpp implements Constructor and call the c function
test.h defines an void function "void abc();"
test.c includes test.h and implements an void function "void abc() {}"
Unresolved external "abc()" referenced from ...unit1.obj
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()
{
}
Solution
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:
#ifndef RTW_HEADER_Multicopter_Model_h_
#define RTW_HEADER_Multicopter_Model_h_
#ifdef __cplusplus
extern "C" {
#endif
void abcdefg();
#ifdef __cplusplus
}
#endif
#endif */
OTHER TIPS
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:
#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.
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.
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.
See the other answers on how to fix this.