I'm trying to wrap an existing 3rd party C++ library to a C interface, so that it can be used in bindings for another language. I'm having trouble figuring out how to wrap a namespaced enum, as opposed to just redefining it:
// Existing C++ 3rd party library header
namespace foo {
enum Fruit {
APPLE = 0,
ORANGE
}
}
So then I have my wrapped.{h,cpp} with an extern "C" block, and I just can't figure out how to export the foo::Fruit enum into the C interface
// wrapped.h
#ifdef __cplusplus
extern "C" {
#endif
// I don't want to do this
typedef enum Fruit {
APPLE = 0,
ORANGE
} Fruit;
#ifdef __cplusplus
}
#endif
#endif
Is it possible to export (mirror) foo::Fruit from the C++ library into my C wrapper as Fruit?
edit: I just noticed that you wanted to wrap an existing library without modifying it.
I fear you are about out of luck then. In general there is just no way of extracting just the enum members out of C++ code without the C compiler choking.
In practice you've got the choice whether to programmatically translate your own set of enumerations into the C++ versions in the interface, try to mirror the C++ exactly and place a bunch of static assertions to double-check, or in theory even filtering them out through scripts.
There are simply no good options here I'm afraid. For the record I would tend to prefer the first of these bad options.
Personally I probably would be lazy and just stick to the C version.
Still, if required and the number of constants is large you can do a bit of macro magic to get a single definition with C-style "namespaces" as required.
First a single header defining all enum entries through a macro:
/* Fruit.h */
FOO_ENUM(APPLE) = 0,
FOO_ENUM(ORANGE)
Then in the C header:
/* C interface */
typedef enum {
# define FOO_ENUM(id) FOO_##id
# include "Fruit.h"
# undef FOO_ENUM
} Foo_Fruit_t;
And finally in the C++ header:
// C++ interface
namespace Foo {
enum Fruit_t {
# define FOO_ENUM(id) id
# include "Fruit.h"
# undef FOO_ENUM
};
}
There are many alternatives of course. For instance if you don't mind polluting the global namespace in C++ then can always define the full enumeration directly in the C interface and copy the individual enum members in the C++ version of the definition.
I ran into this particular problem with enums in a C wrapper for a C++ library recently and it caused quite a headache.
My solution is shown in the following mostly minimal working example but it is terribly inelegant in places. It is essentially a translation approach.
One must be wary not to declare anything twice with regard to the enums. The example passes int, a string or array of char and an enum.
A library header written in C++. This is the library that will be wrapped. MyClass.h:
#ifndef __MYCLASS_H
#define __MYCLASS_H
#include <iostream>
namespace MyNamespace {
using namespace std;
enum EnumControlInterface {HIDController=1, UVCController=2};
class MyClass {
private:
int m_i;
string m_text;
EnumControlInterface _controller;
public:
MyClass(int val);
~MyClass();
void int_set(int i);
void string_set(string text);
int int_get();
string string_get();
void writeEnum(EnumControlInterface MyInterface);
EnumControlInterface readEnum();
};
};
#endif
The C++ implementation of MyClass.cpp:
#include "MyClass.h"
namespace MyNamespace {
MyClass::MyClass(int val) {
cout << "MyClass is being created" << endl;
cout << "The parameter passed to the MyClass constructor is: " << val << endl;
}
MyClass::~MyClass() {
cout << "MyClass is being destroyed" << endl;
}
void MyClass::writeEnum(EnumControlInterface MyInterface) {
_controller = MyInterface;
cout << "The interface control Enum is set in MyClass.cpp as: " << _controller << endl;
}
EnumControlInterface MyClass::readEnum() {
return _controller;
}
void MyClass::string_set(std::string text) {
m_text = text;
}
string MyClass::string_get() {
return m_text;
}
void MyClass::int_set(int i) {
m_i = i;
}
int MyClass::int_get() {
return m_i;
}
}
A "C wrapper" header file MyWrapper.h which wraps MyClass.h:
#ifndef __MYWRAPPER_H
#define __MYWRAPPER_H
#ifdef __cplusplus
namespace MyNamespace {
extern "C" {
#endif
typedef enum WrapperEnumControlInterface {WrapHIDController=1, WrapUVCController=2} WrapperEnumControlInterface;
typedef struct MyClass MyClass;
MyClass* newMyClass(int val);
void MyClass_int_set(MyClass* v, int i);
int MyClass_int_get(MyClass* v);
void MyClass_string_set(MyClass* v, char* text);
char* MyClass_string_get(MyClass* v);
void MyClass_writeEnum(MyClass* v, WrapperEnumControlInterface MyInterface);
WrapperEnumControlInterface MyClass_readEnum(MyClass* v);
void deleteMyClass(MyClass* v);
#ifdef __cplusplus
}
}
#endif
#endif
The "C wrapper" implementation is written in a mixture of C and C++. Specifically the function definitions have to be C and the parameters passed and returned have to be C types as well. Inside the functions and inside the preprocessor areas __cplusplus C or C++ should be fine.
One can not, for example, ask a function inside the extern "C" block to accept the type std::string. It would defeat the objective of the wrapper: to expose only C code that operates the underlying C++ library. extern "C" determines what is exposed without name mangling (see questions about name mangling in C++). __cplusplus is defined by (many) C++ compilers.
MyWrapper.cc:
#include "MyClass.h"
#include "MyWrapper.h"
#include <vector>
namespace MyNamespace {
extern "C" {
MyClass* newMyClass(int val) {
return new MyClass(val);
}
void deleteMyClass(MyClass* v) {
delete v;
}
void MyClass_int_set(MyClass* v, int i) {
v->int_set(i);
}
int MyClass_int_get(MyClass* v) {
return v->int_get();
}
void MyClass_string_set(MyClass* v, char* text) {
//convert incomming C char* to a C++ string
string stringToSend = string(text);
cout << "the string received from the program by the wrapper is " << text << endl;
cout << "the string sent to the library by the wrapper is " << stringToSend << endl;
v->string_set(stringToSend);
}
char* MyClass_string_get(MyClass* v) {
string result = v->string_get();
cout << "the string received from the library by the wrapper is " << result << endl;
// Convert the C++ string result to a C char pointer and return it. Use vectors to do the memory management.
// A vector type of as many chars as necessary to hold the result string
static vector<char> resultVector(result.begin(), result.end());
cout << "the data in the vector who's pointer is returned to the program by the wrapper is: " << &resultVector[0] << endl;
return (&resultVector[0]);
}
void MyClass_writeEnum(MyClass* v, WrapperEnumControlInterface MyInterface) {
v->writeEnum((EnumControlInterface)MyInterface);
}
WrapperEnumControlInterface MyClass_readEnum(MyClass* v) {
EnumControlInterface result = v->readEnum();
return (WrapperEnumControlInterface)result;
}
}
}
A C program that calls the C++ library via the wrapper Cproject.c:
#include "MyWrapper.h"
#include "stdio.h"
int main(int argc, char* argv[]) {
struct MyClass* clsptr = newMyClass(5);
MyClass_int_set(clsptr, 3);
printf("The int read back in Cproject.c is: %i\n", MyClass_int_get(clsptr));
MyClass_writeEnum(clsptr, WrapUVCController);
printf("The enum read back in Cproject.c is: %d\n", MyClass_readEnum(clsptr));
MyClass_string_set(clsptr, "Hello");
char *textReadBack = MyClass_string_get(clsptr);
printf("The text read back in Cproject.c is: %s \n", textReadBack);
deleteMyClass(clsptr);
return 0;
}
And just for completeness a C++ project that calls the C++ library directly without the use of the wrapper CPPProgram.cpp, so short!:
#include "MyClass.h"
#include <iostream>
using namespace std;
using namespace MyNamespace;
int main(int argc, char* argv[]) {
MyClass *c = new MyClass(42);
c->int_set(3);
cout << c->int_get() << endl;
c->writeEnum(HIDController);
cout << c->readEnum() << endl;
c->string_set("Hello");
cout << c->string_get() << endl;
delete c;
}
The MyClass C++ class is compiled to a static library, the wrapper is compiled to a shared library there is no particular reason, both could be static or shared.
The C program that calls the wrapper library (Cproject.c) must be linked with a C++ compiler (G++ etc.)
Obviously this example doesn't have a serious application. It is based on https://www.teddy.ch/c++_library_in_c/ in terms of structure but with the enum bits added in.
Often the person writing the wrapper doesn't have access to the source code of the library they're trying to wrap (MyClass.cpp in this case) they will have the .so or .dll or .a or .lib for Linux and Windows shared and static libraries respectively. It is not necessary to have the source code for the C++ library. Only the header file(s) for the C++ library are needed to write an effective wrapper.
I have written this out partly to provide a more verbose answer to the original question, one that can be copied compiled easily and played around with but also because this is the only way I have been able to solve the problem so far and it is not satisfactory in my view. I would like to be able to wrap the enums in the same way one wraps the public member functions not re-create the enums inside the wrapper with slightly different names.
Sources of related information that proved useful:
https://www.teddy.ch/c++_library_in_c/
How to cast / assign one enum value to another enum
Developing C wrapper API for Object-Oriented C++ code
Converting a C-style string to a C++ std::string
Returning pointer from a function
std::string to char*
Of course all unsafe, wrong etc. coding practices are my fault entirely.
Related
I would like to make a function that can print the contents of another function without breaking the functionality of the copied function.
For example:
int functionToCopy()
{
int a{ 5 };
int b{ 6 };
return a + b;
}
void printCopiedFunction()
{
some magical code to print the contents of the first function;
}
int main()
{
std::cout << functionToCopy() << '\n';
std::cout << printCopiedFunction() << '\n';
return 0;
}
Output:
11
int functionToCopy()
{
int a{ 5 };
int b{ 6 };
return a + b;
}
I'm only a beginner and C++ is my first language. I've done a lot searching and thinking but the only way I could think of is just literally copying the function and making a 2nd function a string, which would double my code and I'd rather avoid that. The program I'd like to do this with currently has 26 functions that would need copying like that so a single function that can be reused would be much preferred.
std::string copiedFunction()
{
std::string str{ R"(
int functionToCopy()
{
int a { 5 };
inb b { 6 };
return a + b;
})"
};
return str;
}
Any help is much appreciated! This is the only time I've ever asked for help like this on a forum but I think this is just beyond my abilities at this point. I understand this may not be possible or it may be very complex and just beyond my scope at this time. Thank you in advance!
C++ does not have reflection so you can't directly do this using the language alone. But you can do it by moving the function to a header file, #includeing that file in your .cpp file, and also building the header file into an object file which makes it contents available as a constant string.
First, put this in foo.h:
inline int functionToCopy()
{
int a{ 5 };
int b{ 6 };
return a + b;
}
Then, using the information from https://stackoverflow.com/a/46221837/4323 use objcopy to create an object file:
objcopy --input binary --output elf64-x86-64 foo.h foo.o
Then change your main file like this:
#include <iostream>
#include <string_view>
#include "foo.h"
extern "C" const char* _binary_foo_h_start; // defined in foo.o
extern "C" const char* _binary_foo_h_size;
std::string_view printCopiedFunction()
{
return {_binary_foo_h_start, _binary_foo_h_size};
}
int main()
{
std::cout << functionToCopy() << '\n';
std::cout << printCopiedFunction() << '\n';
}
And link foo.o into your executable at build time.
Note that objcopy is available on Linux and some other systems, you may need to look for an equivalent on your platform. For example if you have xxd: https://stackoverflow.com/a/411000/4323
On Windows you can embed the text file (which is the header file) as a "resource" in your executable, and load the resource at runtime, like this: Embed Text File in a Resource in a native Windows Application
I want to call a C function from a C++ dll by its address.
I know how to do it where the return type is known from this separate question: Calling a function through its address in memory in c / c++.
However, if I do not know the return type, what can I do? I've tried "typedef auto", but it seems you cannot use auto like that.
If the returning type is really unknown or it doesn't matter, you can use void in your function definition, or if it is any pointer you can use void *, but if the function is in a C coded DLL, and you'll use it in a C++ code, then you can utilize and share almost every type defined in your C code, because C++ it's a superset of C.
That said, I prepared a small example with a structure called PyObject shared in C and C++ codes.
To do this, is better creating a header with the shared types/definitions:
#ifndef PYOBJECT_DLL_H
#define PYOBJECT_DLL_H
#ifdef __cplusplus
extern "C" {
#endif
// Common structure definition
typedef struct PyObject{
int field1;
char *field2;
} PyObject;
// Public function pointer type declaration
typedef PyObject *(*__stdcall getPyObject_t)(int arg1, const char *arg2);
#ifdef __cplusplus
}
#endif
#endif // PYOBJECT_DLL_H
Let's suppose that the C code with the exported function is something like:
#include "pyobject.h"
#include <stdlib.h>
#ifdef __cplusplus
extern "C"
#endif
__declspec(dllexport) PyObject * getPyObject(int arg1, char *arg2);
PyObject *getPyObject(int arg1, char *arg2){
PyObject *obj = (PyObject *)malloc(sizeof(PyObject));
obj->field1 = arg1;
obj->field2 = arg2;
return obj;
}
Finally the C++ code using the function and data created in the library would be:
#include "pyobject.h"
#include <iostream>
#include <windows.h>
int main() {
HINSTANCE dll = LoadLibrary("pyobject.dll");
if (dll == NULL) {
std::cerr << "Cannot open pyobject.dll. Error: " << GetLastError() << "\n";
return 1;
}
getPyObject_t getPyObject = (getPyObject_t) GetProcAddress(dll, "getPyObject");
if (getPyObject == NULL) {
std::cerr << "Cannot locate 'getPyObject' function in dll. Error: " << GetLastError() << "\n";
FreeLibrary(dll);
return 2;
}
PyObject *obj = getPyObject(3, "test");
std::cout << "PyObject == { field1: " << obj->field1 << ", field2: \"" << obj->field2 << "\"}\n";
FreeLibrary(dll);
return 0;
}
Edit
As #raymondchen pointed in his comment, ignoring the return type when the C function returns a large aggregate (e.g. struct) it's not a good idea, because the C function expects that the caller already has had reserved stack space to store the returned aggregate, but if the caller treats the function as void or anything else, then compiler will not reserve that space, causing unpredictable effects (probably ending with Segmentation fault error).
To avoid it, it's always better to define the correct type in both C and C++ codes (or in the common header), especially when the C function returns an aggregate.
This has been driving me nuts for a long time now. I have followed every tutorial I could find on the internet (here are couple examples[ [1], [2] of the maybe half dozen good ones found via Google search), and still no clear explanation. Although it seems it must be something fairly simple as that lack of a documented explanation implies that it's something most people would take for granted.
How do I load a custom module into Lua?
On the advice of questions like this one, I have written a module that builds a shared library with the expectation that I would be able to load it through a require call. However, when I do that I get undefined symbol errors, despite those exact symbols appearing in the list from the command nm -g mylib.so.
Those two tutorials I linked before aim to create executables that look wrappers of the *.lua file. That is, the built *.exe file should be called to run the Lua program with the custom module.
I understand that these types questions are asked here fairly frequently (as noted in this answer), but I am still at a loss. I tried some of the binding packages (Luabind and OOLua), but those didn't work out great (e.g. my earlier question--which I did ultimately figure out, sort of).
I have implemented a class in C++
I have wrapped the constructors, destructors, and functions with thunks
I have built it errorless-ly as a shared library
Yet no matter what I get undefined symbol: ... errors when I try to load it as mod = require('mylib.so'). How do I do this?
Working Example of a Library of Functions
For the record, just registering a basic function works fine. The below code, when built as libluatest.so, can be run in Lua using the commands:
> require('libluatest')
> greet()
hello world!
libluatest.cpp
extern "C"
{
#include <lualib.h>
#include <lauxlib.h>
#include <lua.h>
}
#include <iostream>
static int greet(lua_State *L)
{
std::cout << "hello world!" << std::endl;
return 0;
}
static const luaL_reg funcs[] =
{
{ "greet", greet},
{ NULL, NULL }
};
extern "C" int luaopen_libluatest(lua_State* L)
{
luaL_register(L, "libluatest", funcs);
return 0;
}
Failing Example of a Class
This is what I am stuck on currently. It doesn't seem to want to work.
myObj.h
#include <string>
class MyObj
{
private:
std::string name_;
public:
MyObj();
~MyObj();
void rename(std::string name);
};
myObj.cpp
extern "C"
{
#include <lualib.h>
#include <lauxlib.h>
#include <lua.h>
}
#include <iostream>
#include "myObj.h"
void MyObj::rename(std::string name)
{
name_ = name;
std::cout << "New name: " << name_ << std::endl;
}
extern "C"
{
// Lua "constructor"
static int lmyobj_new(lua_State* L)
{
MyObj ** udata = (MyObj **)lua_newuserdata(L, sizeof(MyObj));
*udata = new MyObj();
luaL_getmetatable(L, "MyObj");
lua_setmetatable(L, -1);
return 1;
}
// Function to check the type of an argument
MyObj * lcheck_myobj(lua_State* L, int n)
{
return *(MyObj**)luaL_checkudata(L, n, "MyObj");
}
// Lua "destructor": Free instance for garbage collection
static int lmyobj_delete(lua_State* L)
{
MyObj * obj = lcheck_myobj(L, 1);
delete obj;
return 0;
}
static int lrename(lua_State* L)
{
MyObj * obj = lcheck_myobj(L, 1);
std::string new_name = luaL_checkstring(L, 2);
obj->rename(new_name);
return 0;
}
int luaopen_libmyObj(lua_State* L)
{
luaL_Reg funcs[] =
{
{ "new", lmyobj_new }, // Constructor
{ "__gc", lmyobj_delete }, // Destructor
{ "rename", lrename }, // Setter function
{ NULL, NULL } // Terminating flag
};
luaL_register(L, "MyObj", funcs);
return 0;
}
}
Compiled into libmyObj.so using a simple CMake build with C++11 standard flags on.
Error
> require('libmyObj')
error loading module 'libmyObj' from file './libmyObj.so':
./libmyObj.so: undefined symbol: _ZN5MyObjC1Ev stack traceback: [C]:
? [C]: in function 'require' stdin:1: in main chunk [C]: ?
I am dealing with Lua 5.1 on Ubuntu 14.04.
I am wondering if it has something to do with the mix of C and C++...
It seems that you do not implement:
MyObj() ; ~MyObj();
and be careful with luaopen_* function, since module name is myObj, function name should be luaopen_libmyObj.
This question has derived from this one.
I have a working program which must be split into multiple parts. In this program is needed to use a variable (now it's a GTK+ one :P) many times in parts of the program that will end up in separated .cpp files.
So, I made a simple example to understand how to make variables available to the program parts. A modified version of the previous code would be:
#include <iostream>
using namespace std;
int entero = 10;
void function()
{
cout<<entero<<endl;
//action1...;
}
void separated_function()
{
cout<<entero<<endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
It is needed to split the code correctly, to have function(), another_function() and main() in separated .cpp files,and make entero avaliable to all of them... BUT:
In the previous question #NeilKirk commented:Do not use global variables. Put the required state into a struct or class, and pass it to functions as necessary as a parameter (And I also have found many web pages pointing that is not recommended to use global variables).
And, as far I can understand, in the answer provided by #PaulH., he is describing how to make variables avaliable by making them global.
This answer was very useful, it worked fine not only with char arrays, but also with ints, strings and GTK+ variables (or pointers to variables :P).
But since this method is not recommended, I would thank anyone who could show what would be the correct way to split the code passing the variables as a function parameter or some other method more recommended than the - working - global variables one.
I researched about parameters and classes, but I'm a newbie, and I messed the code up with no good result.
You need to give the parameter as a reference if you want the same comportement as a global variable
#include <iostream>
using namespace std;
// renamed the parameter to avoid confusion ('entero' is valid though)
void function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value
//action1...;
}
void separated_function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value again
//action2...;
}
int main( int argc, char *argv[] )
{
int entero = 10; // initializing the variable
// give the parameter by reference => the functions will be able to modify its value
function(entero);
separated_function(entero);
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
output:
10
11
12
Defining a class or struct in a header file is the way to go, then include the header file in all source files that needs the classes or structures. You can also place function prototypes or preprocessor macros in header files if they are needed by multiple source files, as well as variable declarations (e.g. extern int some_int_var;) and namespace declarations.
You will not get multiple definition errors from defining the classes, because classes is a concept for the compiler to handle, classes themselves are never passed on for the linker where multiple definition errors occurs.
Lets take a simple example, with one header file and two source files.
First the header file, e.g. myheader.h:
#ifndef MYHEADER_H
#define MYHEADER_H
// The above is called include guards (https://en.wikipedia.org/wiki/Include_guard)
// and are used to protect the header file from being included
// by the same source file twice
// Define a namespace
namespace foo
{
// Define a class
class my_class
{
public:
my_class(int val)
: value_(val)
{}
int get_value() const
{
return value_;
}
void set_value(const int val)
{
value_ = val;
}
private:
int value_;
};
// Declare a function prototype
void bar(my_class& v);
}
#endif // MYHEADER_H
The above header file defines a namespace foo and in the namespace a class my_class and a function bar.
(The namespace is strictly not necessary for a simple program like this, but for larger projects it becomes more needed.)
Then the first source file, e.g. main.cpp:
#include <iostream>
#include "myheader.h" // Include our own header file
int main()
{
using namespace foo;
my_class my_object(123); // Create an instance of the class
bar(my_object); // Call the function
std::cout << "In main(), value is " << my_object.get_value() << '\n';
// All done
}
And finally the second source file, e.g. bar.cpp:
#include <iostream>
#include "myheader.h"
void foo::bar(foo::my_class& val)
{
std::cout << "In foo::bar(), value is " << val.get_value() << '\n';
val.set_value(456);
}
Put all three files in the same project, and build. You should now get an executable program that outputs
In foo::bar(), value is 123
In main(), value is 456
I prefer to provide a functional interface to global data.
.h file:
extern int get_entero();
extern void set_entero(int v);
.cpp file:
static int entero = 10;
int get_entero()
{
return entero;
}
void set_entero(int v)
{
entero = v;
}
Then, everywhere else, use those functions.
#include "the_h_file"
void function()
{
cout << get_entero() << endl;
//action1...;
}
void separated_function()
{
cout << get_entero() << endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<< get_entero() <<endl;
//something else with the mentioned variables...;
return 0;
}
If you do not plan to modify the variable, it is generally ok to make it global. However, it is best to declare it with the const keyword to signal the compiler that it should not be modified, like so:
const int ENTERO = 10;
If you are using multiple cpp files, also consider using a header file for your structures and function declarations.
If you are planning on modifying the variable, just pass it around in function parameters.
I have a command line (+HTTP interface) audio application in C, which currently is being compiled with gcc on Mac OSX, but which I would like to keep this application linux compatible.
However, I would like to use the freeverb3 library. This is in C++. I would prefer not to convert all my code to C++. I don't (as far as I can see) need to call any C code from C++, nor will I need to use C++ objects in my C code. Simple method calls passing arrays of doubles plus a few ints as arguments will be all that I need in terms of interaction from my main application an the C++ code.
From some quick googling, it seems that I can write a C++ interface module, which can then expose some c compatible functions that I can call to make use of freeverb3. I"ve written a micro example to see how this might work. For this example, I have a dummy c++ file called test.cpp:
#include <iostream>
using namespace std;
class test_class
{
int a;
public:
int get_a();
void set_a( int v );
};
int test_class::get_a()
{
return a;
}
void test_class::set_a( int v )
{
a = v;
}
static test_class *c;
extern "C"
{
void init();
void set( int v );
int get();
}
void init()
{
c = new test_class();
}
void set( int v )
{
c->set_a( v );
}
int get()
{
return c->get_a();
}
I have a dummy c file that calls the functions:
#include <stdio.h>
/* Forward declaratoins for extern "C" functions in C++ code */
void init();
int get();
void set( int v );
/* C language code that references functions in C++ code */
int main()
{
init();
set( 55 );
printf( "value: %d\n", get() );
set( get() + 12 );
printf( "value: %d\n", get() );
return 0;
}
And, I have a makefile that creates an executable.
test: test.o user.o
g++ -o test user.o test.o
test.o: test.cpp
g++ -c test.cpp
user.o: user.c
gcc -c user.c
Is this a good way of using C++ code from C? Is there a better/more sophisticated/more traditional way of achieving this aim?
You might want to think about it the other way.
Write your higher level application in C++, invoke the C++ library where you want without complications and call all your current C modules from the C++ level.
IMHO, this is easier to achieve than doing the same with C as high level.
If you intend to use more than one C++ object from C you need to pass an extra instance pointer (this) to the C wrapper functions:
struct A {
A();
~A();
void set(int);
};
The C wrapper:
extern "C"
{
struct A* a_create(void);
void a_destroy(struct A*);
void a_set(struct A*, int);
}
You may also like to catch all C++ exceptions in the C wrapper functions and convert them to error codes.
Pass a pointer to your object instead of using a static variable.
C++ class:
class Foo
{
public:
void doStuff();
};
Common include file:
#ifdef __cplusplus
extern "C"
{
#endif
void Foo_doStuff(void* handle);
void* Foo_create();
void Foo_destroy(void* handle);
#ifdef __cplusplus
}
#endif
Wrapper functions
void Foo_doStuff(void* handle)
{((Foo*)handle)->doStuff();}
void* Foo_create()
{return new(nothrow)Foo;}
void Foo_destroy(void* handle)
{delete (Foo*)handle;}
Not sure whether this goes from C to C++ but it is well worth looking into Swig
Make an extern "C" wrapper in C++, e.g.
// myWrapper.h
#ifdef __cplusplus
extern "C"
{
#endif
void func1(void);
int func2(void);
void func3(char const *str_ptr, size_t len);
#ifdef __cplusplus
}
#endif
// myWrapper.cpp
#include "myWrapper.h"
#include "your_cpp_library.h"
void func3(char const *str_ptr, size_t len)
{
std::string s(str_ptr, str_ptr + len);
call_cpp_function(s);
}
// etc.
In your C code you #include "myWrapper.h" and call those functions. Make sure that:
The code in myWrapper.h stays in the common subset of C and C++
You do not do any cross-boundary resource allocation
The latter might work but it's best to avoid it to be safe. The latter point means that if memory is to be allocated, it must be allocated and freed by the same side; e.g. you can't have the C++ side call malloc and give a pointer to the C side, and then have the C side call free. You have to pass the pointer back to whoever allocated it and let them free it.
Important: as Alf says in a comment, you must have main() in C++ and use the C++ linker , when doing C - C++ inter-linking. This is not a big hurdle though; you can rename your C code's main() function to main2(), and have the C++ code do extern "C" int main2(); and call it.