0

Background: We're implementing a dynamic library in C++ that extends the functionality of a C program. For one of the main structs used in the C program, we would like to add our own library specific fields. Currently when we need a new field, we ask nicely that the developers of the C program add a field for us and we end up having a massive casting mess. I was wondering if we could instead do the following:

Header file of main program:

#ifdef __cplusplus
extern "C" {
#endif
/* ... */
typedef struct ImportantStruct {
/* Definitions */
} ImportantStruct
/* ... */
#ifdef __cplusplus
}
#endif

Our Header File:

//...
class ObjectType : public ImportantStruct {
// Our extra fields
}
//...

I guess I have two questions:

1) Is this even legal?

2) What problems does this create when the C program tries to use the struct part of the object?

shroudednight
  • 605
  • 4
  • 16
  • 3
    Sounds like life would be much easier if you just use composition rather than inheritance... – Rook Nov 08 '12 at 18:53
  • What will you do with your C struct ? Are you just importing the C struct ? Normally, inheriting from C struct is ok - remember C code in a `extern "C"` is parsed by a C++ compiler... – Synxis Nov 08 '12 at 19:05
  • I agree in theory that composition would be a much, much better solution. And if I were doing this from scratch, I would use composition in a heartbeat. The problem is that we currently have a `typedef ImportantStruct ObjectType` and many, many places that access fields directly. If I changed the typedef to inheritance, those access would still be legal, and I get better control of the object lifecycles. However, as there possibly other immediate advantages to composition, I'll definitely re-consider it as an option. – shroudednight Nov 08 '12 at 19:49

2 Answers2

1

Since the ImportantStruct is a POD structure (automatically it has standard layout), and since ObjectType doesn't have other base types and if it doesn't have virtual methods, it also has a standard layout. Therefore it can be used as a struct in C.

1) Is this even legal?

Yes, it is.

2) What problems does this create when the C program tries to use the struct part of the object?

If your c function doesn't try to over-write it, you are safe. You can overwrite it like this :

void foo( struct ImportantStruct *s )
{
 memset( s,0, sizeof(*s) );
}

If it does, then it depends on what is in ImportantStruct, and whether there are padded bytes.

Structure like this :

typedef struct {
  int a;
  char b;
} ImportantStruct;

might have padded bytes removed when made base class.

Anyway, I would use composition, and avoid any kind of problems. But you have to make sure it is the first member, and that the ObjectType has standard layout.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
0

The derived approach should work, just mind the resulting alignment. I would not make assumptions on the resulting size/offsets in the "extended" POD. Some compilers may remove padding of the base class. So the derived C++ POD may be of different size from resp. extended flat C struct.

More details on the layout of derived objects: c-data-alignment-member-order-inheritance

Also for your purposes of extending POD you may use struct keyword over class. Not a big difference, just the struct members are public by default. It also kind of expresses your POD-intent (though it's not enforced).

Community
  • 1
  • 1
vmsnomad
  • 319
  • 2
  • 7