4

I have a header declaring functions that take pointers to C++ objects as parameters. The implementaton is in a seperate C++ file. How can I include this header in C and use the functions in C even though the arguments need to be C++ object pointers?

CheedleBoy
  • 43
  • 1
  • 1
  • 4
  • Why can't you switch your calling code to C++? It's not difficult to switch, as C++ is mostly backwards compatible. Chances are all you have to do is change what you're compiling it as, and won't need to change the code itself. – outis Oct 25 '10 at 04:20
  • 2
    Also, possible duplicate of ["Calling 'C++' class member function from 'C' code"](http://stackoverflow.com/questions/3583353/calling-c-class-member-function-from-c-code), ["How to call C++ function from C?"](http://stackoverflow.com/questions/2744181/how-to-call-c-function-from-c) – outis Oct 25 '10 at 04:23
  • are you able to modify the C++ header at all? – jalf Oct 25 '10 at 11:02

7 Answers7

7

Unfortunately, my first attempt answered the wrong question....

For the question you did ask...

You can, as someone point out, pass around void *'s. And that's what I would also recommend. As far as C is concerned, pointers to C++ objects should be totally opaque.

C++ functions can be labeled extern "C" as well if they are in the global namespace. Here is an example:

myfunc.hpp:

#ifdef __cplusplus
extern "C" {
#endif

extern int myfunction(int, void *ob);

#ifdef __cplusplus
}
#endif

myfunc.cpp:

#include "myfunc.hpp"

void myfunction(int x, void *vobptr)
{
    ClassType *ob = static_cast<ClassType *>(vobptr);
}

afoofile.c

#include "myfunc.hpp"

void frobble(int x, void *opaque_classtype_ptr) {
    myfunction(x, opaque_classtype_ptr);
    /* do stuff with buf */
}

The other option is to do basically the same thing with creative use of typedefs in C. This, IMHO, is quite ugly, but here is an example anyway:

myfunc.hpp:

#ifdef __cplusplus
extern "C" {
#else
typedef void ClassType;  /* This is incredibly ugly. */
#endif

extern int myfunction(int, ClassType *ob);

#ifdef __cplusplus
}
#endif

myfunc.cpp:

#include "myfunc.hpp"

void myfunction(int x, ClassType *ob)
{
    // Do stuff with ob
}

afoofile.c

#include "myfunc.hpp"

void frobble(int x, ClassType *opaque_classtype_ptr) {
    myfunction(x, opaque_classtype_ptr);
    /* do stuff with buf */
}
Omnifarious
  • 54,333
  • 19
  • 131
  • 194
  • The more usual idiom for conditionally using `extern "C"` can be found in my answer at http://stackoverflow.com/questions/2941126/c-explicit-dll-loading-first-chance-exception-on-non-extern-c-functions/2941360#2941360 (it won't fit nicely into a comment). It's doesn't involve repeating your prototypes, so it's much less prone to typos. – Ken Bloom Oct 25 '10 at 04:43
  • @Ken Bloom - that makes sense, and I'll edit my version to conform, though it makes the stupid trick in the second example less clear. – Omnifarious Oct 25 '10 at 05:01
  • if it makes the pointer trick less clear, then *don't* use it. – Ken Bloom Oct 25 '10 at 14:05
  • if it's incredibly ugly, what's the right way?! – Alexis Dec 01 '21 at 06:35
  • 1
    @Alexis - The other way that involves a `static_cast` inside the C++ function. The ugliness of the other way is that the function takes a different type depending on which language sees the declaration. For an ordinary pointer type this is likely not a problem. But for a function pointer type, this may cause all kinds of strange things. In general, playing fast and loose with the type system like the 'ugly way' does is just a bad idea. – Omnifarious Dec 11 '21 at 20:53
4

If your C code just needs to pass the pointers around, and eventually pass it back to some C++ that'll actually deal with the object it points to, you should be able to use a void * in the C code, and cast back to T * when it goes back into C++.

If you plan on the C code actually using the pointer, you're pretty much stuck with reverse engineering what your compiler happens to do, and trying to emulate it closely enough to make things work. Even at best, this is going to be ugly and fragile.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

Make a wrapper module that's C++ but whose external functions are declared extern "C". This will allow you to access C++ code cleanly from C. Naturally the wrapper should replace any pointers to types not representable in C (i.e. classes) with either void pointers (the quick and dirty solution) or pointers to incomplete struct types (which would provide some level of type-safety as long as they're used consistently.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
0

Leaving this as after reading allsorts of posts on this topic, this was the easiest to follow.

http://research.engineering.wustl.edu/~beardj/Mixed_C_C++.html

Also, in netbeans the example ran out of the box without having to touch the makefile.

James Scott
  • 1,032
  • 1
  • 10
  • 17
0

The secret is "extern C", whose primary purpose is the prevention of name decoration.

Alexander Rafferty
  • 6,134
  • 4
  • 33
  • 55
0

You can't. You'll have to create a C-compatible abstraction layer:

typedef struct foowrapper *foohandle;

foohandle foo_create();
void foo_delete(foohandle);

int foo_getvalue(foohandle);
void foo_dosomething(foohandle, const char* str);
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
-1

Check out this link:-

http://developers.sun.com/solaris/articles/mixing.html

The link contains the following topics:

  • Using Compatible Compilers

  • Accessing C Code From Within C++ Source

     -  Accessing C++ Code From Within C Source
    
  • Mixing IOstream and C Standard I/O

  • Working with Pointers to Functions

  • Working with C++ Exceptions

  • Linking the Program

Aditya Singh
  • 9,512
  • 5
  • 32
  • 55
  • 1
    1. posting links with no explanation, description or summary is discouraged on SO (it makes your answer useless if the page you linked to goes down, it makes it harder for a reader to get an overview of the various answers, and some people like to know that what they're clicking on isn't just spam, or even that it is relevant to the question). And 2. you didn't even format it as a link. – jalf Oct 25 '10 at 11:01