tags:

views:

252

answers:

5

Is there a simple way to work with C++ objects directly from C? I want to expose some classes from C++ to C or to FFI(foreign function interface). Sure, I can write a stuff like that:

class Foo{
....
};

void *make_foo(...){
Foo *ptr = new Foo(..)

return static_cast<void *>(ptr);
}

..

int *foo_method1(void *fooptr, ...){
Foo *ptr = static_cast<Foo*>(fooptr);
}

But there is a simpler method?

+8  A: 

That, in general, is the simplest method.

Remember, too, that you'll need to use extern "C" on all of your C "wrapper" methods, as well.

Reed Copsey
+7  A: 

You almost there. Prefix your standalone functions with extern "C" to turn off the C++ compiler's name mangling.

For example:

extern "C" void *make_foo(...){
  Foo *ptr = new Foo(..)

  return static_cast<void *>(ptr);
}
eduffy
+1  A: 

There's not really a simpler way to do it. You could use SWIG to go to another language with user defined types that are more than aggregates of data, but converting to C you'll have to use C's idea of objects.

Todd Gardner
+1  A: 

You can use Verrazano/Fetter to generate CFFI bindings for C++ code. But it requires GCC-XML and I'm not sure about its portability.

dmitry_vk
+1  A: 

If it's possible, then have your classes derive from a struct. You can then use pointers to this struct in the C code:

// C++ code
extern "C" struct Cfoo {};
extern "C" struct Cbar {};

class foo : public Cfoo {};
class bar : public Cbar {};

// C API
extern "C" {
    struct Cfoo;
    struct Cbar;
}

It's not strictly an error, however gcc at least warns about converting between pointers with different types.

void foo (void) {
    struct Cfoo * pf;
    struct Cbar * pb;
    pf = pb;        // gcc warns
}

If you cannot inherit, then use a similar idea but have the C structure store a pointer to the C++ object, and again just forward declare the structures in the C API:

// C++ code
class foo {};
class bar {};

extern "C" struct Cfoo { foo * pFoo; };
extern "C" struct Cbar { bar * pBar; };

// C API
extern "C" {
    struct Cfoo;
    struct Cbar;
}

The disadvantage here is that the lifetime of the Cfoo and Cbar object needs to be taken care of.

Richard Corden