Browse DevX
Sign up for e-mail newsletters from DevX


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.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

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