UDT Sharing
The simplest form of sharing a declaration of a user-defined type (UDT) between C and C++ is sticking to the lowest common denominator of C. The following C struct can be used as-is in a C++ program:
typedef struct String
{
char * pstr;
int size;
} String;
C doesn't recognize the keyword
class so you must stick to
struct. In addition, using the same token for the tag (the name before the
{) and the typedef name (the name following the
}) guarantees that the following code will compile successfully in both languages:
//works both in C and C++
char buff[100];
String mystr; //no 'struct' before String
mystr.pstr=&buff[0];
mystr.size=sizeof(buff);
And yet, C++ users would expect to find member functions,
conversion operators, and overloaded operators in
String. The fact that these C++ features will not be usable in C is no excuse for depriving C++ users of these conveniences. Your goal is to have a single declaration of
String that will be shared both by C and C++ users, without sacrificing essential C++ features. How do you accomplish this feat?
A C++ Overhaul
All data members in String must remain implicitly public. protected and private are out of the question as they might break binary compatibility between C and C++. Additionally, all C++ features must appear inside an #ifdef-endif block like this:
typedef struct String
{
>#ifdef __cplusplus
//anything you put here will be visible only from C++
#endif
char * pstr;
int size;
} String;
Here's the augmented
String struct:
typedef struct String
{
#ifdef __cplusplus
char * getpstr() {return pstr;}
void init(int sz=0) {pstr=sz? new char[sz]:0;
size=sz;}
operator const char* () const {return pstr;}
int getsize() const {return size;}
char& operator[] (int id) {return pstr[id];}
const char& operator[] (int id) const {return pstr[id];}
#endif
char * pstr;
int size;
} String;
C++ users can now use
String as an ordinary C++ class with member functions, overloaded operators and conversion operators:
String s={0}; //zero initialize all data members
s.init(10);
s[5]='a';
cout<<s<<endl; //invoking const char* conversion operator
cout<<s.getsize()<<endl;
delete[] s.getpstr(); //'delete[] s;' will work too
C users on other hand will keep using
String like this:
#include <stdio.h>
String s1;
s1.pstr=(char *) malloc(10);
s1.size=10;
printf("%s\n", s1.pstr);
printf("%d\n", s1.size);
free(s.pstr);
Unbelievable as it may seem, the two code listings above use the same
String type.