开发者

Why should non-POD types in C++ be opaque to C clients?

gcc 4.4.4 c89

I was just reading a discussion at DevX about calling C++ code from C since I have to do s开发者_运维知识库omething similar. I am just wondering what user Vijayan meant by "make sure that non POD types in C++ are opaque to C clients."

Many thanks for any suggestions,


C can only deal with POD types.

Consequently, you cannot pass objects of non-POD types to C programs (by value). Also, if you pass pointers of non-POD types to C programs, they can't interact with the objects pointed to.


POD = Plain old data structure = C structs, no virtual methods, etc. You need to write wrapper functions for C to access non-POD types (i.e., classes).

More on POD: http://en.wikipedia.org/wiki/Plain_old_data_structure


For a type to be opaque means you can't look inside it: it's a "black box" that can be passed around but not inspected or manipulated directly by the C code. You typically refer to the object using either heap-allocated memory and void*s, or using functions to determine the necessary length and buffers.

For example, a C++ object might contain a std::string, but the layout of a std::string is not specified in the C++ Standard, so you can't write C code that directly reads from or writes to the string (at least, not without having a total understanding of the std::string layout, manually revalidated every time the compiler/STL is updated).

So, to allow C code to access the object, you might write C-callable functions such as:

#if __cplusplus
extern "C" {
#endif
void*       object_new();
const char* object_get_string(void* p_object);
void        object_set_string(void* p_object, const char* s);
void        object_delete();
#if _cplusplus
}
#endif

With C++ implementation ala:

class Object { std::string string_; ... }
void* object_new() { return new Object; }
const char* object_get_string(void* p) { return ((Object*)p)->string_.c_str()); }
...

Here, the object_XXX functions provide the C code with a safe way to use the Object.


Making the type opaque means, as per the line in the link:

typedef struct base base ; /* opaque */

makes the name of the handle available to C code, but not the definition of the type. This means that the C code cannot access any members directly, but has to go through the interface functions.

Note that you do not have to make a cast to a generic , i.e. void*, pointer, although doing so is one option, as per 9dan's answer.

Note that such a style of interface is in my experience a very nice way to manage encapsulation even in pure C code, just as in the standard C streams library.


Making opaque to clients means nothing special. C stream file I/O (FILE* f = fopen) API is the typical example that present opaque handle to clients.

Apparently C can not handle non-POD type so you must hide C++ implementation from C clients but provide access method.

Example:

C++ Implementation

class MyLibrary {
MyLibrary();
~MyLibrary();
int DoSomething();
...
}

Declaration for C clients

typedef void* OPAQUEHANDLE;

extern OPAQUEHANDLE MyLibrary_OpenLibrary();
extern void MyLibrary_CloseLibrary(OPAQUEHANDLE h);
extern int MyLibrary_DoSometing(OPAQUEHANDLE h);

Implementation for C clients (in .cpp file)

extern OPAQUEHANDLE MyLibrary_OpenLibrary()
{
    return new MyLibrary;
}

extern void MyLibrary_CloseLibrary(OPAQUEHANDLE h)
{
    delete (MyLibrary*) h;
}

extern int MyLibrary_DoSometing(OPAQUEHANDLE h)
{
    return ((MyLibrary*)h)->DoSomething();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜