dcsimg
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

A Guide to C++ and C Interoperability  : Page 2

Using C++ code in C apps is difficult and tricky, though not impossible, contrary to popular belief. Find out how to share class declarations between the two languages and how to leverage C apps with high-end C++ features behind your C compiler's back.


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



Thanks for your registration, follow us on our social networks to keep up-to-date