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.
Related
I have a static C library that I want to port to C++, in the C library I got some global variables that store some common data used by the functions for example:
// global variable in the C library
int global_number_of_cpu_cores;
init_global_vars()
{
global_number_of_cpu_cores = get_info();
}
void lib_function()
{
// use global_number_of_cpu_cores
}
when using the library, it must be first initialized by the init function but in C++, the object's constructors are executed before the main function, so I cannot code:
class class_lib
{
class_lib()
{
// use global_number_of_cpu_cores but this is uninitialized!
}
}
Also, you can initialize global variables with functions:
int program_var = lib_function(); // lib_function uses global_number_of_cpu_cores but this is unintialized!
what is a decent/elegant way to solve this when designing a C++ library?
how do well-designed C++ libraries like Boost, Qt, etc solve this? any idea?
What you can do - simply create a C wrapper interface for C++ I.e. something like following:
In header file, e.g. foo.h
#ifndef __FOO_H_INCLUDED__
#define __FOO_H_INCLUDED__
#ifdef __cplusplus
extern "C" {
#endif
void print_logical_cpus()
#ifdef __cplusplus
}
#endif / * extern "C" */
#endif / * __FOO_H_INCLUDED__ */
in the implementation file e.g. foo.cpp
#include "foo.h"
#include <cstdio>
#include <thread>
struct GlobalSettings {
GlobalSettings():
logical_cpus(std::thread::hardware_concurrency())
{}
std::size_t logical_cpus;
};
static GlobalSettings __gsettings;
extern "C" {
void print_logical_cpus()
{
std::printf("Logical cpus %z", __gsettings.logical_cpus);
}
}
If you still need to port on raw C, there are compiler specific tricks to run functions before and after main.
GCC uses attribute((constructor)) and attribute((destructor)))
MS VC++ uses __declspec(allocate(".CRT$XLC"))
I have a C++ header and cpp files like abc.hpp and abc.cpp which has 2 classes that is class A and class B, am trying to write a C layer containing different methods which calls the C++ layer methods, to call the C++ methods I need to create the instance of Class A and then use this instance to call C++ methods, I have created a C layer but tried different ways to create an instance of class B but it was not possible.
This is ABC.hpp
#ifndef ABC_HPP
#define ABC_HPP
namespace utils {
using std::vector;
using std::string;
class __declspec(dllexport) A
{
protected:
string m_color;
string m_type;
public:
A() {
// TODO: Complete the constructor by intializing everything
m_color = "";
m_type = "";
}
void setColor(string icolor){m_color = icolor;}
void setType(string itype){m_type = itype;}
string getColor(){return m_color;}
string getType() {return m_type;}
virtual ~A() {};
};
class __declspec(dllexport) B
{
// Member Variables
protected:
string file_name;
string place_name;
public:
void setFilename(fname){file_name = fname;}
void setPlaceName(pname){place_name = pname;}
string getFilename(){return file_name;}
string getplaceName() {return place_name;}
void getRes();
};
};
#endif
Similarly we have ABC.cpp
Next I create the C layer xyz_c.h
#ifndef XYZ_H
#define XYZ_H
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) int getPlaceNames(char** oNames);
#ifdef __cplusplus
}
#endif
#endif
Next I create XYZ.cpp
#include "XYZ.h"
#include "ABC.h"
#ifdef __cplusplus
extern "C" {
#endif
int getResults(char** oNames)
{
//here I need to create the instance of B to Call C++ layer getRes()
}
#ifdef __cplusplus
}
#endif
You cannot. C++ was designed to allow it to use the whole set of C legacy code already written, but the other side is not possible... simply because when C was designed there was no C++ available, and C doesn't have constructs as C++ has to be able to link routines written in C.
This means that if you want to combine C and C++ code, the program must be linked as a C++ program (built as) and you can include every routine you want (you can compile individual modules as C modules) but you have to access them from the C++ code including a extern "C" linkage statement in the C++ code (and never the reverse)
C++ has a naming convention for methods and c++ functions that includes information in the name about the types and number of parameters to allow for overloading and to include the object instance in the parameter list. This is simply unknown for a C compiler, so you cannot easily guess the name that the linker uses for something so simple as a void f(void) function (it can be something like 1f4void (yes, starting with a digit) making it impossible to be accessed from C (as C identifiers must start with a letter or underscore). If you declare f as extern "C" f(void), then you can call it from C modules, and it can even be implemented in C (and compiled in c), and the linker will know it as _f (or f is in use today also, depending on the compiler)
You can even write the int main(int argc, char **argv) funtion as a C function, but when you link it, you will need to use the C++ linker, if you want your program to include C++ code.
The proper way to do this is as follows. In your "C" interface code, you should have functions matching the c++ interface with the addition of a void* parameter. This parameter will be used to hold the instance for future usage by XYZ.
SO I would add a abc.c, with definitions as:
void setFilename(void* b, char *fname){
((B*)b)->setFilename(fname);
};
of course you will need to define also creator function such as:
void* CreateB(){
return (void*)new B();
}
In questions such as this, compatibility between C++ classes/structs and C structs is explained as possible as long as all members are of the same type, in the same order, and no virtual members are declared.
That's my problem. I have virtual methods, and I would very much like to keep them when manipulating the struct in C++.
Let's examine this toy example. It's meant to be a C and C++ compatible struct defined in a single header file.
mystr.h:
#ifdef __cplusplus
#include <string>
struct mystr_base {
virtual ~mystr_base() {}
virtual std::string toString() = 0;
};
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct mystr
#ifdef __cplusplus
: public mystr_base
#endif
{
const char* data;
#ifdef __cplusplus
std::string toString() {
return std::string(data);
}
#endif
};
#ifdef __cplusplus
}
#endif
This may not be exactly pretty, but will do for the example. In a real scenario, the C and C++ variants may be in separate headers, with the C++ struct extending a POD struct. Regardless of implementation, the issue of alignment is still present.
With this example, if a C program was written that passes an instance of mystr to a C++ function, the vtable will interfere with the alignment:
test.h:
#include "mystr.h"
#ifdef __cplusplus
extern "C"
#endif
void mycxxfunc(struct mystr str);
test.cpp:
#include <stdio.h>
#include "test.h"
void mycxxfunc(mystr str) {
printf("mystr: %s\n", str.data);
}
main.c:
#include "test.h"
int main(int argc, char** argv) {
const char* testString = "abc123";
struct mystr str;
str.data = testString;
mycxxfunc(str);
}
$ g++ -c test.cpp && gcc main.c test.o
$ ./a.out
Segmentation fault (core dumped)
(presuming that this is because the C++ function is attempting to read data from beyond the end of the struct's allocated memory)
What's the best way to enable this C-C++ interoperability while still retaining the ability to use virtual functions in C++?
I do not recommend you to clutter your header file with #ifdefs.
The first thing you should do in this case if you want to retain some kind of virtualization and C compatibility at the same time is:
Make your C++ and C type an opaque pointer to the representation.
Put implementation details in a .cpp file.
An idea follows.
Header file:
struct MyStrImpl;
struct MyStr {
MyStrImpl * impl;
};
extern "C" MyReturnType myFunction(MyStr myStr);
Implementation in .cpp file:
struct MyCppString {
virtual ...
};
#ifdef __cplusplus
struct MyStrImpl : public MyCppString {
};
#else
struct MyStrImpl {
};
#endif
MyStr::MyStr() : impl{new MyStrImpl{}} {
}
This way you have a type that can be used from both C and C++.
Advantages:
No #ifdef in header file.
Compatible with C/C++ and consumable from both languages.
Disadvantages:
Lose overloading due to extern "C".
Must use a C-style interface (but can implement with C++-like with virtual functions interface in your .cpp file.
You cannot have both a C-compatible type and virtual functions in a header file at the same time without cluttering it with #ifdef, something that I do not recommend since it can be inconvenient if you need to refactor code.
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 have been following this guide on how to call a member function of a C++ object from C. As I've understood it, the C code should interpret the class as a struct of the same name, and whenever it wants to call a function through an object of this class it should use an intermediate callback function. The header looks like this:
// CInterface.h
#ifdef __cplusplus
...
class CInterface
{
public:
...
void OnMessage(U8* bytes); // I want to call this function from C.
private:
...
};
#else
typedef
struct CInterface
CInterface;
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__STDC__) || defined(__cplusplus)
//extern void c_function(CInterface*); /* ANSI C prototypes (shouldn't be needed) */
extern CInterface* cpp_callback_function(CInterface* self, unsigned char * bytes);
#else
//extern void c_function(); /* K&R style (shouldn't be needed) */
extern CInterface* cpp_callback_function(unsigned char * bytes);
#endif
#ifdef __cplusplus
}
#endif
The C code that fails right now looks like this:
// main.c
#include "CInterface.h"
int main(int argc, char* argv[])
{
void* ptr;
int *i = ptr; // Code that only compiles with a C compiler
CInterface cinterface; // This should declare a struct
}
The error is: error C2079: 'cinterface' uses undefined struct 'CInterface'.
It sounds like the header is being read as c++ code as the struct is not defined, but main.c is being compiled by C according to Visual Studio (I also double checked this by adding some C-specific code). However, if I add parentheses like this:
CInterface cinterface();
the code compiles which makes no sense to me as it now is an object which shouldn't work in C.
The callback function is implemented in a third file, CInterface.cpp, which acts as the "intermediate".
So the question is how I solve this error message, or if I got the entire approach wrong. It's the first time I mix C/C++ code and I'm relatively new to both languages.
In your example CInterface is only defined for C++. If you take a closer look at the example you linked you'll notice that this is also the case for the Fred class.
From C you can only pass around pointers to CInterface and you have to rely on C++ functions defined with C linkage to actually manipulate CInterface instances.
Otherwise you could define a struct as a means to pass around data between C and C++. Just ensure its definition is declared as extern "C" when used from C++:
#ifdef __cplusplus
extern "C" {
#endif
struct CandCPlusPlus {
// ...
};
#ifdef __cplusplus
}
#endif