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()
{

}
Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top