Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

struct as a base class - C/C++ interoperability

Tags:

c++

c

oop

class

struct

I recall I saw somewhere some code which used to have a struct as a base class, and a C++ class as a derived class

struct Base_Struct
{

}

class Derived : Base_Struct
{
  ...
}

And the point is that a pointer to Base_Struct* was passed from the C++ files to some C files which then managed to use some function pointers in Base_Struct.

My question is: if I pass Base_Struct* to a C file, will the C code be able to use the Base_Struct completely? What about the derived class?

like image 606
Marco A. Avatar asked Dec 05 '13 16:12

Marco A.


People also ask

Can struct be used as base class for another class?

Structs are value types while classes are reference types. Structs can be instantiated without using a new operator. A struct cannot inherit from another struct or class, and it cannot be the base of a class.

Can struct be used as base class for inheritance *?

Yes, struct can inherit from class in C++. In C++, classes and struct are the same except for their default behaviour with regards to inheritance and access levels of members.

Is struct the same as class in C?

In C++, structs and classes are pretty much the same; the only difference is that where access modifiers (for member variables, methods, and base classes) in classes default to private, access modifiers in structs default to public.

Can we define class with struct?

Yes you can. In c++, class and struct are kind of similar. We can define not only structure inside a class, but also a class inside one. It is called inner class.


3 Answers

If I pass Base_Struct* to a C file, will the C code be able to use the Base_Struct completely?

If it's a standard-layout class, and the C compiler uses the same ABI for such classes as the C++ compiler, then it can access all the data members. Obviously, it couldn't access any member functions or static members, since such things don't exist in C and would have to be left out of any C-compatible definition of the structure.

What about the derived class?

You couldn't define that class in a C program, so it couldn't do anything interesting with the pointer.

like image 137
Mike Seymour Avatar answered Oct 13 '22 21:10

Mike Seymour


Maybe it can work for the base class. But that is on very special case:

  • POD struct
  • same packing
  • same runtime if you allocate/deallocate in C and C++
  • pure C syntax
  • etc...

But it will never directly for the derived class.

But that create so many restriction that I would provide a C level API to allocate an manipulate those pointers defined as alias on "void*" (I'm not even sure you can do such aliases this in pure C).

Something like:

 typedef void* BaseStructPtr;

 BaseStructPtr AllocateBase(/* constructor params */);
 BaseStructPtr AllocateDerived(/* constructor params */);

 TypeOfField1 GetField1(BaseStructPtr ptr);
 TypeOfField2 GetField2(BaseStructPtr ptr);

 /* etc... */
like image 30
Johan Avatar answered Oct 13 '22 21:10

Johan


In your sample yes a C compiler will be able to use the Base_Struct* pointer and access members. You can use the same struct definition in C and CPP files without problems. As long as it's the Cpp who cast the struct for the C file the compiler will do the job.

void Give_Typed_Pointer_to_C_Function(Base_Struct* pStruct) {...}
void Give_Pointer_to_C_Function(void* pStruct) {...}
Base_Struct A;
Derived B;
Give_Typed_Pointer_to_C_Function(&A);         // OK
Give_Typed_Pointer_to_C_Function(&B);         // OK 
Give_Pointer_to_C_Function(&A);               // OK    
Give_Pointer_to_C_Function(&B);               // wrong
Give_Pointer_to_C_Function((Base_Struct*)&B); // OK 

For this to work you have to use the same alignment and packing of struct but as you pass pointer I suppose you are same project so it should be already be the case.

You can even do more, if you keep struct in same order

struct S1 { int x; 
            int y;
          };
class C1 {  int x;
            int y;
            int add(int,int); 
          };
void Give_Typed_Pointer_to_C_Function(S1 *pStruct);
C1 object;
Give_Typed_Pointer_to_C_Function((S1*)&object);  // OK

// an safer alternative as you can't have to be sure that S1 and C1 match
struct C1 { int x;
            int y;
#ifdef __cplusplus
            int add(int,int); 
#endif
          };

If you put Cpp keyword like class/public/private and methods in struct with defines. And if you don't use inheritance it will work as well.

like image 44
ColdCat Avatar answered Oct 13 '22 21:10

ColdCat