Search code examples
c++clanguage-interoperability

Possible compatibility issues inheriting from a C struct


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?


Solution

  • 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.