I'm trying to include some C function in a C++ program.
I get some issue with a function declaration that contains array as parameter.
extern "C" {
double Test( int nVar1, double f[nVar1] ) {
return f[nVar1-1];
}
}
int main() {
cout << "!!!Hello World!!!" << endl;
double f[2] = {1.0,2.0};
Test(2, f);
return 0;
}
I get following errors
'f' was not declared in this scope
'nVar1' was not declared in this scope
use of parameter outside function body before ']' token
I use Atollic 8.0 (GCC and C -std=gnu11)
Any help will welcome
Thank-you
extern "C" isn't for compiling c inside cpp source. It's only to use ABI of C inside cpp source/header: mangling, calling conventions, exception handling... (thanks to Ajay Brahmakshatriya)
By mangling, I want to say the internal unique name of function used by compiler/linker. C mangling is really different to c++ mangling, and so not compatible. To find C function inside c++, you have to say to compiler/linker under which internal unique name the function is known.
extern "C" only switches which ABI has to be used, including mangling used to create internal unique name and how function has to be called, not to switches compilation mode.
If you really want to compile c code, you have to put your code inside a c source file and compile it separately. And use extern "C"to declare function in cpp environment, to allow c++ code to use it. BUT declaration of function has to be compatible with c++, and double Test( int nVar1, double f[nVar1] ) isn't.
function.c, compile with gcc -c:
double Test( int nVar1, double f[] ) {
return f[nVar1-1];
}
function.h, compatible c and c++:
#ifndef _FUNCTION_H
#define _FUNCTION_H
#ifdef __cplusplus
extern "C" {
#endif
double Test( int nVar1, double f[] );
#ifdef __cplusplus
}
#endif
#endif
main.cpp, compile with g++ -c:
#include "function.h"
int main() {
cout << "!!!Hello World!!!" << endl;
double f[2] = {1.0,2.0};
Test(2, f);
return 0;
}
And finally, link everything with g++ linker:
g++ function.o main.o -o my_program
See example here:
C++ source, compilation c, compilation c++ and linkage
C source
The problem is with array size. It cannot be variable, should be const. If you need to pass an array of variable size then just pass the pointer to its first element:
double Test( int nVar1, double * f) {
What do you recommend to compile with g++ a such C function without having to rewritte the full code included in this legacy function
#ifdef __cplusplus
extern "C" {
#endif
int ComputedF(int nPoints, int nFunc, double x[], double f[nPoints][nFunc], double df[nPoints][nFunc])
#ifdef __cplusplus
}
#endif
Thank-you
Related
I know this.
Calling C function from C++:
If my application was in C++ and I had to call functions from a library written in C. Then I would have used
//main.cpp
extern "C" void C_library_function(int x, int y);//prototype
C_library_function(2,4);// directly using it.
This wouldn't mangle the name C_library_function and linker would find the same name in its input *.lib files and problem is solved.
Calling C++ function from C???
But here I'm extending a large application which is written in C and I need to use a library which is written in C++. Name mangling of C++ is causing trouble here. Linker is complaining about the unresolved symbols. Well I cannot use C++ compiler over my C project because thats breaking lot of other stuff. What is the way out?
By the way I'm using MSVC
You need to create a C API for exposing the functionality of your C++ code. Basically, you will need to write C++ code that is declared extern "C" and that has a pure C API (not using classes, for example) that wraps the C++ library. Then you use the pure C wrapper library that you've created.
Your C API can optionally follow an object-oriented style, even though C is not object-oriented. Ex:
// *.h file
// ...
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void* mylibrary_mytype_t;
EXTERNC mylibrary_mytype_t mylibrary_mytype_init();
EXTERNC void mylibrary_mytype_destroy(mylibrary_mytype_t mytype);
EXTERNC void mylibrary_mytype_doit(mylibrary_mytype_t self, int param);
#undef EXTERNC
// ...
// *.cpp file
mylibrary_mytype_t mylibrary_mytype_init() {
return new MyType;
}
void mylibrary_mytype_destroy(mylibrary_mytype_t untyped_ptr) {
MyType* typed_ptr = static_cast<MyType*>(untyped_ptr);
delete typed_ptr;
}
void mylibrary_mytype_doit(mylibrary_mytype_t untyped_self, int param) {
MyType* typed_self = static_cast<MyType*>(untyped_self);
typed_self->doIt(param);
}
I would do it in the following way:
(If working with MSVC, ignore the GCC compilation commands)
Suppose that I have a C++ class named AAA, defined in files aaa.h, aaa.cpp, and that the class AAA has a method named sayHi(const char *name), that I want to enable for C code.
The C++ code of class AAA - Pure C++, I don't modify it:
aaa.h
#ifndef AAA_H
#define AAA_H
class AAA {
public:
AAA();
void sayHi(const char *name);
};
#endif
aaa.cpp
#include <iostream>
#include "aaa.h"
AAA::AAA() {
}
void AAA::sayHi(const char *name) {
std::cout << "Hi " << name << std::endl;
}
Compiling this class as regularly done for C++. This code "does not know" that it is going to be used by C code. Using the command:
g++ -fpic -shared aaa.cpp -o libaaa.so
Now, also in C++, creating a C connector:
Defining it in files aaa_c_connector.h, aaa_c_connector.cpp. This connector is going to define a C function, named AAA_sayHi(cosnt char *name), that will use an instance of AAA and will call its method:
aaa_c_connector.h
#ifndef AAA_C_CONNECTOR_H
#define AAA_C_CONNECTOR_H
#ifdef __cplusplus
extern "C" {
#endif
void AAA_sayHi(const char *name);
#ifdef __cplusplus
}
#endif
#endif
aaa_c_connector.cpp
#include <cstdlib>
#include "aaa_c_connector.h"
#include "aaa.h"
#ifdef __cplusplus
extern "C" {
#endif
// Inside this "extern C" block, I can implement functions in C++, which will externally
// appear as C functions (which means that the function IDs will be their names, unlike
// the regular C++ behavior, which allows defining multiple functions with the same name
// (overloading) and hence uses function signature hashing to enforce unique IDs),
static AAA *AAA_instance = NULL;
void lazyAAA() {
if (AAA_instance == NULL) {
AAA_instance = new AAA();
}
}
void AAA_sayHi(const char *name) {
lazyAAA();
AAA_instance->sayHi(name);
}
#ifdef __cplusplus
}
#endif
Compiling it, again, using a regular C++ compilation command:
g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so
Now I have a shared library (libaaa_c_connector.so), that implements the C function AAA_sayHi(const char *name). I can now create a C main file and compile it all together:
main.c
#include "aaa_c_connector.h"
int main() {
AAA_sayHi("David");
AAA_sayHi("James");
return 0;
}
Compiling it using a C compilation command:
gcc main.c -L. -laaa_c_connector -o c_aaa
I will need to set LD_LIBRARY_PATH to contain $PWD, and if I run the executable ./c_aaa, I will get the output I expect:
Hi David
Hi James
EDIT:
On some linux distributions, -laaa and -lstdc++ may also be required for the last compilation command. Thanks to #AlaaM. for the attention
Assuming the C++ API is C-compatible (no classes, templates, etc.), you can wrap it in extern "C" { ... }, just as you did when going the other way.
If you want to expose objects and other cute C++ stuff, you'll have to write a wrapper API.
You will have to write a wrapper for C in C++ if you want to do this. C++ is backwards compatible, but C is not forwards compatible.
export your C++ functions as extern "C" (aka C style symbols), or use the .def file format to define undecorated export symbols for the C++ linker when it creates the C++ library, then the C linker should have no troubles reading it
#include <iostream>
//////////////
// C++ code //
//////////////
struct A
{
int i;
int j;
A() {i=1; j=2; std::cout << "class A created\n";}
void dump() {std::cout << "class A dumped: " << i << ":" << j << std::endl;}
~A() {std::cout << "class A destroyed\n";}
};
extern "C" {
// this is the C code interface to the class A
static void *createA (void)
{
// create a handle to the A class
return (void *)(new A);
}
static void dumpA (void *thisPtr)
{
// call A->dump ()
if (thisPtr != NULL) // I'm an anal retentive programmer
{
A *classPtr = static_cast<A *>(thisPtr);
classPtr->dump ();
}
}
static void *deleteA (void *thisPtr)
{
// destroy the A class
if (thisPtr != NULL)
{
delete (static_cast<A *>(thisPtr));
}
}
}
////////////////////////////////////
// this can be compiled as C code //
////////////////////////////////////
int main (int argc, char **argv)
{
void *handle = createA();
dumpA (handle);
deleteA (handle);
return 0;
}
You can prefix the function declaration with extern “C” keyword, e.g.
extern “C” int Mycppfunction()
{
// Code goes here
return 0;
}
For more examples you can search more on Google about “extern” keyword. You need to do few more things, but it's not difficult you'll get lots of examples from Google.
I have a C++ file and its header file. I need to include this header file in a C code and use the functions in it.
When the cpp.h file is compiled through main.c, compilation fails because of the C++ linkage.
On using the macro __cplusplus stream and string are not resolved, is there some way to compile the cpp.h file through and execute?
I have given a outline of my code only.
C++ header file cpp.h:
struct s1
{
string a;
string b;
};
typedef struct s1 s2;
class c1
{
public:
void fun1(s2 &s3);
private:
fun2(std::string &x,const char *y);
};
C++ file cpp.cpp:
c1::fun1(s2 &s3)
{
fstream file;
}
c1::fun2(std::string &x,const char *y)
{
}
C file main.c:
#include "cpp.h"
void main()
{
c1 c2;
s1 structobj;
c2.fun1(&structobj);
printf("\n value of a in struct %s",structobj.a);
}
Basically, you can't.
You need to put only C functions in your header file.
You put them in a extern "C" block this way:
#ifdef __cplusplus
extern "C"
{
#endif
extern void myCppFunction(int n);
#ifdef __cplusplus
}
#endif
The extern "C" block is not recognized by a C compiler, but the C++ compiler need it to understand he have to consider functions inside as C functions.
In your cpp file you can define myCppFunction() so that she uses any C++ code, you will get a function C code can use.
Edit: I add a full example of how to link a program with a C main() using some C++ functions in a module.
stackoverflow.c:
#include "outputFromCpp.h"
int main()
{
myCppFunction(2000);
return 0;
}
outputFromCpp.h:
#ifndef OUTPUT_FROM_CPP_H
#define OUTPUT_FROM_CPP_H
#ifdef __cplusplus
extern "C"
{
#endif
extern void myCppFunction(int n);
#ifdef __cplusplus
}
#endif
#endif
outputFromCpp.cpp:
#include "outputFromCpp.h"
#include <iostream>
using namespace std;
void myCppFunction(int n)
{
cout << n << endl;
}
Compiling and linking:
gcc -Wall -Wextra -Werror -std=gnu99 -c stackoverflow.c
g++ -Wall -Wextra -Werror -std=c++98 -c outputFromCpp.cpp
g++ -o stackoverflow.exe stackoverflow.o outputFromCpp.o -static
You cannot link such a program with gcc.
If you want to link with gcc you need to put all the C++ code in a shared library, I don't put an example as it would be a bit platform dependent.
This can be done by introducing a wrapper to c++ function. The C function calls the wrapper function which inturn calls the desired C++ function (including member functions).
More details are available here
I'm trying to compile my code, but when I do, it happens:
In function `main':
/home/emilio/CB/QAP/main.cpp|42|undefined reference to `start_timers()'
/home/emilio/CB/QAP/main.cpp|45|undefined reference to `elapsed_time()'
I have 'timer.c' and 'timer.h' as extern functions to measure time.
timer.c
#include <stdio.h>
#include <time.h>
#include "timer.h"
clock_t start_time;
double elapsed;
void start_timers(){
start_time = clock();
}
double elapsed_time( type )
TIMER_TYPE type;
{
elapsed = clock()- start_time;
return elapsed / CLOCKS_PER_SEC;
}
timer.h
extern clock_t start_time;
extern double elapsed;
int time_expired();
void start_timers();
double elapsed_time();
typedef enum type_timer {REAL, VIRTUAL} TIMER_TYPE;
main.cpp
#include "timer.h"
...
double time;
start_timers();
launch_algorithm();;
time = elapsed_time();
...
How can I fix it? Thanks!
You are mixing C and C++. To use C stuff in a C++ file, you have to wrap the header like so
#ifdef __cplusplus
extern "C"
{
#endif
extern clock_t start_time;
extern double elapsed;
int time_expired();
void start_timers();
double elapsed_time();
typedef enum type_timer {REAL, VIRTUAL} TIMER_TYPE;
#ifdef __cplusplus
}
#endif
I'm not sure how this will work with your functions, as you haven't put the parameters in the function prototypes in the header file. It is generally considered best practice to add them, so if it still doesn't work, try that.
So it seems that there are a few holes in your understanding, I will try to fill in the gaps...
The main issue is that the interoperability of C and C++.
in C having a function named dog that takes an int and returns void -> void dog(int) will be translated consistently to the object file as a symbol named something like _dog or similar (but what that symbols name is is well defined by the platform and ABI that you are using).
in C++ there is another layer of abstraction necessary by the way that they have chosen to adopt function overloading.. so our function void dog(int) could be named _void_dog_int or similar (this is called name mangling)...
so if you want to use standard C functions in a C++ program you get some strangeness...
when you write in a C++ program
dog.h (interface to some library or just C code)
void dog(int);
something.cpp
#include <doglib/dog.h>
void someMethod(void)
{
dog(4);
}
the compiler generates an object that expects dog to be named in a c++ way (_void_dog_int)
but the linker doesn't find that symbol in dog.o or libdog.a or whatever the object file is (because in the object file the symbol is named _dog like a std C program).
So there is a way to tell the C++ compiler that the symbol is a C symbol... the construct is:
extern "C" void dog(int);
or
extern "C"
{
void dog(int);
...
}
so that would fix our problems, except that it borks our C compiler!
so things have to get a little more complicated.
#ifdef __cplusplus
extern "C"
{
#endif
void dog(int);
...
#ifdef __cplusplus
}
#endif
These macros expand so that in C++ they have an extern "C", and in C they do not...
The issue with the global var is similar... C++ and std C deal with unqualified globals differently... to support namespaces or some C++ construct (I haven't looked into that specifically)
You need to make some changes to the .c and .h file; as well as the extern "C" guards.
In timer.h, the function declarations should be:
int time_expired(void);
void start_timers(void);
double elapsed_time(TIMER_TYPE type);
And in the timer.c file, those three lines should be the same (minus the semicolons).
Current you have what is known as "K&R style" function headers:
double elapsed_time( type )
TIMER_TYPE type;
{
elapsed = clock()- start_time;
return elapsed / CLOCKS_PER_SEC;
}
The problem with this sort of function header is that it does not form a prototype. The compiler will not complain in most cases if you get the list of arguments wrong. You just get undefined behaviour at runtime.
By using prototypes, the compiler will check that the function has the right number and types of arguments passed, and convert arguments if necessary.
It's conceivable that the C++ compiler will get name-mangling wrong if the functions are not prototyped.
NB. I saw in another comment you said "I changed .c by .cpp" . If you meant that you renamed timer.c to timer.cpp - don't do that! C and C++ are different languages. You should leave it as timer.c. Your compiling setup should include both a C and a C++ compiler. The C compiler compilers the C code, and the C++ compiler compiles the C++ code, with the extern "C" directives indicating how to glue the two together.
I'm running into a mysterious situation with the GCC compiler. So I've got the following files:
//main.cpp
#include "mleak_cpp.h"
int main(int argc, char* argv[])
{
foo();
__memory_malloc(10,"hello",5);
return 0;
}
//mleak_cpp.h
......
void foo(void);
void* __memory_malloc(size_t size, const char* file, int line);
//mleak_cpp.cpp
//definitions of the functions;
void foo(void){printf("foo\n");
void* __memory_malloc(size_t size, const char* file, int line){
printf("%s,%d\n",file,line);
InitDoubleLinkList();
void* p = malloc(size);
if(p == NULL)
return NULL;
__DuLinkList* pListNode;
pListNode = (__DuLinkList*)malloc(sizeof(__DuLinkList));
pListNode->address = p;
pListNode->memorysize = size;
pListNode->file = file;
pListNode->line = line;
InsertBlockToList(pListNode);
return p;
}
For some reason, the call to void foo(void) is fine, but the call to "__memory_malloc" goes down with a linker error, "undefined reference" blah blah. What's the difference between the two functions that causes the different behaviour?
I tried adding "extern C" to the "#include" directive, so main.cpp reads:
extern "C"{
#include "mleak_cpp.h"
}
and adding the keyword "extern" before the declarations of the functions, and this time the call to "foo()" fails too with the same error.
I appreciate any help from you guys
You're placing extern "C" in the wrong place.
If main.c is truly a C file, and mleak_cpp.cpp is truly a C++ function, then you need to put an extern "C" ahead of the definition of __memory_malloc() like so:
extern "C" void* __memory_malloc(size_t size, const char* file, int line){
// ...
}
If you put extern "C" in the mleak_cpp.h file, it needs to be guarded:
#ifdef __cplusplus
extern "C" {
#endif
/* ... body of header ... */
#ifdef __cplusplus
}
#endif
Also, it's not clear why foo works in your example above, when one file calls __foo() but the other file defines foo(). I assume something more is at play, such as an editing error in your question.
extern "C" is for C++, not C, and tells it that the function's name shouldn't be mangled. In C code, you should never see this. Generally, you put it in header files, and you guard it, like this:
#ifdef __cplusplus
extern "C" {
#endif
/* C and C++ compatible header file body here */
#ifdef __cplusplus
} /* end extern "C" */
#endif
If you do it this way though, you need to include the header file in both your C and C++ files, so that the C++ compiler knows to use C linkage.
You can put the extern "C" in front of the function definition in C++ instead and leave it out of the header, but this only works if you only include the headers in C code, so it's recommended to do it the way I pointed out above.
I have a C++ function defined in a .h file as follows and implemented in a .cpp file:
extern "C" void func(bool first, float min, float* state[6], float* err[6][6])
{
//uses vectors and classes and other C++ constructs
}
How can I call func in a C file? How do I set up my file architecture / makefile to compile this?
Thanks!
You call the function from C in the normal way. However, you need to wrap the extern "C" in an preprocessor macro to prevent the C compiler from seeing it:
#ifndef __cplusplus
extern "C"
#endif
void func(bool first, float min, float* state[6], float* err[6][6]);
Assuming you're working with GCC, then compile the C code with gcc, compile the C++ code with g++, and then link with g++.
To call it in C, all you need to do is call it normally. Because you told the compiler to use the C calling conventions and ABI with extern "C", you can call it normally:
func(args);
To compiler, use this for the C++:
g++ -c -o myfunc.o myfunc.cpp
Then this for the C:
gcc -c -o main.o somec.c
Than link:
g++ -o main main.o myfunc.o
Make sure that the C++ header for the function uses ONLY C CONSTRUCTS. So include things like <vector> in the .cpp file instead.
call it in C using
func(/* put arguments here */);
By saying extern "C" you are asking the compiler not to mangle your names. Otherwise, C++ compiler would tend to mangle them (i.e. add additional symbols to make them unique) before the linker.
You'll also want to make sure you have setup to use C calling convention.
//header file included from both C and C++ files
#ifndef __cplusplus
#include <stdbool.h> // for C99 type bool
#endif
#ifdef __cplusplus
extern "C" {
#endif
void func(bool first, float min, float* state[6], float* err[6][6]);
#ifdef __cplusplus
} // extern "C"
#endif
// cpp file
#include "the_above_header.h"
#include <vector>
extern "C" void func(bool first, float min, float* state[6], float* err[6][6]);
{
//uses vectors and classes and other C++ constructs
}
// c file
#include "the_above_header.h"
int main() {
bool b;
float f;
float *s[6];
float *err[6][6];
func(b,f,s,err);
}