This is an completely rewritten version of an earlier question; I think the first version omitted important details; this one provides all the context.
I have a header of some C++ API. The API declares a few classes like this:
class Foo
{
public:
inline void Bar(void);
/* more inlines */
private:
inline Foo();
/* maybe more inline constructors */
}
I.e. no members, all functions are inline and public, except constructors. Constructors are private, so, as far as I understand C++, I cannot really call them. To create these objects I'm supposed to use auto_ptr
s to them:
class FooAutoPtr : public std::auto_ptr<Foo>
{
public:
inline FooAutoPtr();
/* one for each Foo constructors */
}
The API also has a second set of functions like this:
void Foo_Bar(void *self);
Foo* Foo_Constructor();
Let's call them core functions, because these are the symbols actually exported from the host app. Not the C++ classes.
Core functions have C linkage (i.e. they declared as extern "C"
), but they are declared as taking and returning C++ types (e.g. they can take a reference: Foo &foo
). Finally the header contains the implementation of the inline functions of the C++ classes. All these functions do the same: they call the core functions. For example, the FooAutoPtr
constructor is like this:
inline FooAutoPtr::FooAutoPtr()
{
reset(Foo_Constructor());
}
From what I understand, the code receives some object that is supposed to be a pointer to Foo
from the host app and changes the auto_ptr
gizmo to point to this object. But to the developer it looks as if it was a true pointer to Foo
. And calling Foo::Bar()
goes like this:
inline Foo::Bar()
{
Foo_Bar(this);
}
This goes for all C++ classes and methods. Clever, huh?
Now, could somebody please explain what does all this mean? :) It's not a true C++ API, is it? To me it looks more like a thin C++ wrapper on top of a C API. If so, can I redeclare the core functions to lose the C++ bits? I understand how to write a C wrapper around C++ (actually, I already wrote it), but, if possible, I'd rather lose the wrapper and use the functions directly. But how do I lose the C++ stuff?
For example, there could be a function with references:
Bar& Foo_GetBar(void* self, const Baz& baz, int& i);
Right now I call it from my C++ wrapper like this:
typedef struct bar bar_t; /* and others */
/*...*/
bar_t*
foo_get_bar(foo_t* foo, baz_t* baz, int* i)
{
return (bar_t*) &Foo_GetBar(foo, *(Baz*)baz, *i);
}
and it works (I have no idea, how). But I'd rather have it redeclared like this:
/* type? */ Foo_GetBar(foo_t*, /* type? /*, /* type? */);
UPDATE: I found an interesting thing that confirms Neil's answer. It is code in Common Lisp that uses the same API. (Naturally, it has to use the C part.) And, from what I can (barely) read in the source, the author simply used pointers in place of of references. Here's a snippet from code that converts C++ declarations into Lisp:
;; use * instead of & - we're not interested in C++ details
line (regex-replace-all "&" line "*")
So that's it :) Thanks, everyone!
In theory, the details of how a compiler treats a reference in an C-linkage declaration is an unspecified implementation detail. However many compilers treat it as if it was a pointer. So if the C++ library header imports Bar& Foo_GetBar(void* self, const Baz& baz, int& i);
then you could try importing it into your C header as bar_t* Foo_GetBar(foo_t* self, const baz_t* baz, int* i);
and it might just work.
#define & * // convert references into pointers.
Stop. Right. There. That was a joke, rather than an attempt to see how many downvotes could be accumulated on a single answer.
But the approach of rewriting the header file to replace references with pointers should certainly work. Because these are C functions, there's no name mangling to worry about, and I've yet to see a compiler that doesn't implement references as pointers. (Is there any other possible way?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With