Anton Kazennikov
Anton Kazennikov

Reputation: 3604

C++ code and objects from C?

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?

Upvotes: 7

Views: 318

Answers (5)

Richard Corden
Richard Corden

Reputation: 21721

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.

Upvotes: 1

dmitry_vk
dmitry_vk

Reputation: 4469

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.

Upvotes: 1

Todd Gardner
Todd Gardner

Reputation: 13521

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.

Upvotes: 1

eduffy
eduffy

Reputation: 40224

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);
}

Upvotes: 7

Reed Copsey
Reed Copsey

Reputation: 564413

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.

Upvotes: 8

Related Questions