I try to access in a C program data received from a C++ library which has been originally designed with structure inheritance:
example:
// C++ data structures
typedef struct _Base
{
public:
int id;
wchar_t* name;
} Base;
typedef struct _Struct1 : Base
{
public:
int valueCount;
} Struct1;
typedef struct _Struct2 : Base
{
public:
int parentID;
int amount;
} Struct2;
I tried using the following data structures in C for mapping.
typedef struct _Base
{
int id;
wchar_t* name;
} Base;
typedef struct _Struct1
{
// Base struct data
int id;
wchar_t* name;
int valueCount;
} Struct1;
typedef struct _Struct2
{
// Base struct data
int id;
wchar_t* name;
int parentID;
int amount;
} Struct2;
But printing the data, it looks like I get wrong values.
Am I missing something, any reference on how C++ represents inherited structure internally?
Thanks in advance!
The C++11 rules on PODs ( What are Aggregates and PODs and how/why are they special? ) specify that don't allow mixing concrete base classes with data members, but in practice for most compilers having a single POD base class is equivalent to encapsulating that class as the first member.
Try specifying your C structs encapsulating the base struct:
typedef struct _Struct1
{
Base base;
int valueCount;
} Struct1;
Note that this won't work if the C++ classes are non-POD (eg have virtual methods).
You might be able to trick your C compiler to produce a structure with the same memory layout of a C++ class, and in many cases that will work, but this is a fairly shaky foundation to build on.
The portable way would be to write accessor functions. Be sure to declare them as extern "C"
.
Illustrative example for a header file (not necessarily clean; typical caveats of writing code in a web form apply :-)):
#ifdef __cplusplus
// C++ declarations go here
class Foo
{
public:
int bar;
};
// C calling conventions follow
extern "C" {
#else
// Make it so your C code can work with Foo* as an incomplete/not-dereferencable
// type.
typedef void Foo;
#endif
// Declare this in a C++ source file to return fooptr->bar
int foo_get_bar(Foo *fooptr);
#ifdef __cplusplus
} // extern "C"
#endif
One possibility to investigate is that the structs you've defined are correct, but that the aligmnents the compilers are using don't match. See:
http://en.wikipedia.org/wiki/Data_structure_alignment
Usually you can set the alignment using compiler switches or #pragma directives. You'd have to read your compiler documentation to find out about that. If you can't contact the authors of the C++ code, you may have to use a debugger to look at the raw memory you're receiving to work out what the alignment/padding is between the different values in the structures.
You can get this kind of problem if one program is compiled for a 64 bit machine and the other for a 32 bit machine. Or it could be down to the different compilers implementations.
You can try using a wrapper layer over the C++ library you are using to output values coming from the C++ to to C rather than using directly what is coming from C++ side. That could work if the overhead from the extra layer would not be significant.
Casting a C++ class might not always work as it keeps member and virtual methods pointers inside the class structure.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.