简体   繁体   中英

C opaque pointer gotchas

I'm working with a legacy C library interface (to C++) that exposes opaque pointers as

typedef void * OpaqueObject

In the library:

OpaqueObject CreateObject()
{
   return new OurCppLibrary::Object();
}

This of course provides absolutely no type safety for clients of this library. Should changing the typedef from a void pointer to structure pointer work exactly the same, but provide a small amount type safety?

typedef struct OpaqueObjectInternal_ *OpaqueObject 
// OpaqueObjectInternal_ is NEVER defined anywhere in client or library code

Are there any alignment issues or other gotchas that I have to worry about now that I am explicitly pointing to a structure, even though I'm really not pointing to one?

There are no gotcha's; that form is preferred exactly because of type safety.

No, alignment is not an issue here. The pointer itself has a known alignment, and the alignment of the object it will point at is only of concern to the library implementation, not the user.

Actually, a C++ class is also a C struct. So you could simply do this:

struct Object;
struct Object* Object_Create(void);

And, the C wrapper in the library thus:

struct Object* Object_Create(void)
{
    return new Object;
}

A method call might look like this:

uint32_t Object_DoSomething( struct Object* me, char * text )
{
    return me->DoSomething( text );
}

I have tried this and I see no downsides.

The first thing to consider with your suggested course is what are you communicating to the others that may have to maintain the code you are writing. Above all other things opaque objects are the C way to indicate to the user of a library that the library maintainer makes absolutely no guarantee as to the implementation of an object other than that the object can be used with the documented functions. By removing the void* you are basically announcing to the world, "I declare this implementation that was once opaque to be stable." This may not be what you want.

Secondly, IMHO you are proposing is the sort of half solution that makes no one happy, a better approach is to develop a wrapper class. This has the added benefit of allowing you to wrap the init and destroy functions that inevitably accompany C style opaque objects in the constructors and destructor of you class. This will allow you to provide resource management as well as type safety to your clients with out a whole lot more work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM