Cannot Mix C Code

I am trying to integrate C sources into the project (based on SimpleTemplate) but I am unable to call a C function from C++, since at runtime I receive an undefined reference error. I have tried to use both

/C++ File/
extern “C” {
#include “cheader.h”
}

and

/cheader.h/
extern “C” {
void func();
}

Any ideas? Could it be due to name mangling?

Unless we see more of the source, there’s not much more we can recommend. You can post relevant sources here or PM me for help.

Your extern “C” declarations look fine, but how are you compiling the C code? is it being run through g++ or gcc? If it’s being compiled as C++ by the IDE but you’re trying to reference it using extern “C”, then yes, name mangling will surely be an issue.

/* ScriptParser.cpp*/
#include <string>
#include <cstdio>
#include “ScriptParser.h”
extern “C” {
#include “tiny_scheme_interpreter.h”
}

bool ScriptParser::init(string initFile) {
FILE *fscript;

printf("Initializing TinyScheme...");
scheme_init(&sc);
puts("Done");


}


/* tiny_scheme_interpreter.h */
...
int scheme_init(scheme *sc);
...


/* tiny_scheme_interpreter.c */
...
int scheme_init(scheme *sc) {
 return scheme_init_custom_alloc(sc,malloc,free);
}
...

I checked the build properties and found that .c and .cpp files are compiled with the same flags but a different variable/macro is used (%ccompilerprefix% and %cppcompilerprefix%) in the command.


echo "building $@";%ccompilerprefix% $(TOOL_PATH)ccppc %DebugModeFlags% %ToolFlags% $(ADDED_CFLAGS) %Includes% $(ADDED_INCLUDES) -DCPU=$(CPU) -DTOOL_FAMILY=$(TOOL_FAMILY) -DTOOL=$(TOOL) -D_WRS_KERNEL   $(DEFINES) -o %OutFile% -c %InFile%

$(CC_ARCH_SPEC) -ansi  -Wall  -MD -MP -mlongcall


echo "building $@";%cppcompilerprefix% $(TOOL_PATH)ccppc %DebugModeFlags% %ToolFlags% $(ADDED_CFLAGS) %Includes% $(ADDED_INCLUDES) -DCPU=$(CPU) -DTOOL_FAMILY=$(TOOL_FAMILY) -DTOOL=$(TOOL) -D_WRS_KERNEL   $(DEFINES) -o %OutFile% -c %InFile%

$(CC_ARCH_SPEC) -ansi  -Wall  -MD -MP -mlongcall

I checked the console output and the function definitely seemed mangled…any ideas on howto change compilation to C?

Is there any particular reason you can’t compile the C as C++ in this case?

I remember when I first placed the tiny_scheme_interpreter source file it had a CPP extension, which I changed to C; when I first tried compiling it, there were errors which indicated that it was definitely being compiled as C; e.g. non-C style comments were shown as an error. It must be the scheme_init() call in the ScriptParser C++ code which is being mangled, in spite of extern “C”.

But if you compile everything as C++, the symbols should match up and the linker should have no problem. I’d focus on just getting it to compile as C++. I don’t know why this should be too much of a problem. If it’s some some stupid persistent project setting that you can’t change or something, try copying the code into new .cpp files.

It seems that this is the simplest solution to this problem. Usually, the C/C++ mixing nastiness is only an issue if you are using a large C code base and/or pre-compiled C library that you want to link with in a C++ application. Since it seems like there is only a single C-style function, just rename it to .cpp and the compiler will compile it as C++.

As to what the problem may be with your current extern “C” way, what is a “scheme *” type defined as? Is it a C type or a C++ class? Consult this FAQ for more information.

Thanks! It works now.
I did not recognize at first that the source file was compiled separately; I wanted to have .c in order to convey the fact that it is a C source file, rather than a C++ class.

I’m now facing the same issue, but this time I cannot merely rename the source file to .cpp because it contains numerous implicit type conversions which are considered errors in C++. Manual typecasting will probably take a week. Maybe I should try calling from inline asm to avoid name mangling issues, or simply rename the C functions to the mangled name…not elegant but this might work.

Or just put the header include inside an extern “C”.

That only works when the file has the extension .cpp (i.e., is compiled as C++).

Exactly… so when you are including the C header file in a .cpp file, you include the header as extern “C”.