News:

This week IPhone 15 Pro winner is karn
You can be too a winner! Become the top poster of the week and win valuable prizes.  More details are You are not allowed to view links. Register or Login 

Main Menu

TITLE: interfacing structs between C and C++

Started by ben2ong2, October 06, 2006, 10:59:44 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ben2ong2

(Newsgroups: comp.std.c++, 26 Mar 97)

WSEYMOUR: You are not allowed to view links. Register or Login

>I'm writing a C++ function that gets called from
>a shrink-wrapped library (presumably written in C)
>and is passed a pointer to a structure.  The library
>function assumes that it is calling a C function.
>I'd like to encapsulate the structure something like:
>
>    struct foo { ... };  // the library's structure
>
>    class bar : private foo
>    {
>        // non-virtual member functions only
>    private:
>        bar();
>        bar(const bar&);
>        bar& operator=(const bar&);
>        ~bar();
>
>        static int static_member_object;
>    };
>
>Is it safe and portable to write my function as:
>
>   void foobar(bar *bp) { ... }
>
>when the argument is really a foo*?  Is this essentially
>the same question as whether it's safe to cast a foo*
>down to a bar*?  (Note that I'm careful not to add any
>virtual member functions or non-static member objects;
>and I can't construct, destruct or assign such an object.)


CLAMAGE: You are not allowed to view links. Register or Login (Steve Clamage)

You are not assured this will work, although it is likely to
work with common implementations. The presence of a base class
removes any assurances about compatibility of bar and foo.

It is safer to derive the C++ class publicly from the C struct,
use the derived class in your C++ code and pass pointers to the base
class (an implicit conversion) to the C library. Example:

struct foo { ... }; // imported from the C header
extern "C" void f1(foo*); // C functions
extern "C" void f2(foo);

class bar : public foo {
   // ... add whatever you want here
};

int main()
{
   bar b;
   f1(&b); // ok, implicit conversion to foo*
   f2(b);  // ok, "sliced" to a foo
}

I realize I'm answering the inverse of the question you asked.

For the question you actually asked, treating a foo as a bar, you
can add a constructor to bar that takes a foo reference or pointer.
Now you don't have to lie to the compiler or use unsafe casts, and
you can add to bar whatever features make it easier to use as a C++
class. (If you add data members, you run the risk of the C++ view
of the class becoming unsynchronized with the C view.) This approach
is not attractive if all the foo objects come from the C program,
since you wind up copying them when you create a bar.

If the foo objects are all created in the C program, you can define
class bar to have a reference member to a foo instead of deriving
from foo:

class bar {
public:
   foo& thefoo; // or maybe make thefoo private
   bar(foo& f) : thefoo(f) { ... }
   ... // whatever else
};

You can call the C functions as
   f1(&b.thefoo);
   f2(b.thefoo);

or you could overload the C functions with inline C++ wrapper functions
   inline void f1(bar* b) { f1(&b->thefoo); }
   inline void f2(bar& b) { f2(b.thefoo); }
You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login