C opaque pointer gotchas - c++

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.

Related

which is good creating void* to object or making self referential? [duplicate]

Microsoft's GDI+ defines many empty classes to be treated as handles internally. For example, (source GdiPlusGpStubs.h)
//Approach 1
class GpGraphics {};
class GpBrush {};
class GpTexture : public GpBrush {};
class GpSolidFill : public GpBrush {};
class GpLineGradient : public GpBrush {};
class GpPathGradient : public GpBrush {};
class GpHatch : public GpBrush {};
class GpPen {};
class GpCustomLineCap {};
There are other two ways to define handles. They're,
//Approach 2
class BOOK; //no need to define it!
typedef BOOK *PBOOK;
typedef PBOOK HBOOK; //handle to be used internally
//Approach 3
typedef void* PVOID;
typedef PVOID HBOOK; //handle to be used internally
I just want to know the advantages and disadvantages of each of these approaches.
One advantage with Microsoft's approach is that, they can define type-safe hierarchy of handles using empty classes, which (I think) is not possible with the other two approaches, though I wonder what advantages this hierarchy would bring to the implementation? Anyway, what else?
EDIT:
One advantage with the second approach (i.e using incomplete classes) is that we can prevent clients from dereferencing the handles (that means, this approach appears to support encapsulation strongly, I suppose). The code would not even compile if one attempts to dereference handles. What else?
The same advantage one has with third approach as well, that you cannot dereference the handles.
Approach #1 is some mid-way between C style and C++ interface. Instead of member functions you have to pass the handle as argument. The advantage of exposed polymorphism is that you can reduce the amount of functions in interface and the types are checked compile time. Usually most experts prefer pimpl idiom (sometimes called compilation firewall) to such interface. You can not use approach #1 to interface with C so better go full C++.
Approach #2 is C style encapsulation and information hiding. The pointer may be (and often is) a pointer to real thing, so it is not over-engineered. User of library may not dereference that pointer. Disadvantage is that it does not expose any polymorphism. Advantage is that you may use it when interfacing with modules written in C.
Approach #3 is over-abstracted C-style encapsulation. The pointer may be really not a pointer at all since user of library should not cast, deallocate or dereference it. Advantage is that it may so carry exception or error values, disadvantage is that most of it has to be checked run time.
I agree with DeadMG that language-neutral object-oriented interfaces are very easy and elegant to use from C++, but these also involve more run-time checks than compile time checks and are overkill when i don't need to interface with other languages. So i personally prefer Approach #2 if it needs to interface with C or Pimpl idiom when it is C++ only.
2 and 3 are slightly less typesafe as they allow to use handles instead of void*
void bluescreeen(HBOOK hb){
memset(hb,0,100000); // no compile errors
}
Approach 3 is not very good at all, as it allows the mixing and matching of handle types that don't actually make sense, any function that takes a HANDLE can take any HANDLE, even if it's compile-time determinable that that is the wrong type.
The downside of Approach 1 is that you have to do a bunch of casting on the other end to their actual types.
Approach 2 isn't that bad, except you can't do any kind of inheritance with it without having to externally query every time.
However, all of this is entirely moot ever since compilers discovered how to implement efficient virtual functions. The approach taken by DirectX and COM is the best- it's very flexible, powerful, and completely type-safe.
It even allows for some truly insane things, like you can inherit from DirectX interfaces and extend it that way. One of the best advantages of this is Direct2D and Direct3D11. They're not actually compatible (which is truly, horrendously stupid), but you can define a proxy type that inherits from ID3D10Device1 and forwards to the ID3D11Device and solve the problem like that. That kind of thing would never even think about being possible with any of the above approaches.
Oh, and last thing: You really, really shouldn't name your types in allcaps.

C++ Class References

Coming from Delphi, I'm used to using class references (metaclasses) like this:
type
TClass = class of TForm;
var
x: TClass;
f: TForm;
begin
x := TForm;
f := x.Create();
f.ShowModal();
f.Free;
end;
Actually, every class X derived from TObject have a method called ClassType that returns a TClass that can be used to create instances of X.
Is there anything like that in C++?
Metaclasses do not exist in C++. Part of why is because metaclasses require virtual constructors and most-derived-to-base creation order, which are two things C++ does not have, but Delphi does.
However, in C++Builder specifically, there is limited support for Delphi metaclasses. The C++ compiler has a __classid() and __typeinfo() extension for retrieving a Delphi-compatible TMetaClass* pointer for any class derived from TObject. That pointer can be passed as-is to Delphi code (you can use Delphi .pas files in a C++Builder project).
The TApplication::CreateForm() method is implemented in Delphi and has a TMetaClass* parameter in C++ (despite its name, it can actually instantiate any class that derives from TComponent, if you do not mind the TApplication object being assigned as the Owner), for example:
TForm *f;
Application->CreateForm(__classid(TForm), &f);
f->ShowModal();
delete f;
Or you can write your own custom Delphi code if you need more control over the constructor call:
unit CreateAFormUnit;
interface
uses
Classes, Forms;
function CreateAForm(AClass: TFormClass; AOwner: TComponent): TForm;
implementation
function CreateAForm(AClass: TFormClass; AOwner: TComponent): TForm;
begin
Result := AClass.Create(AOwner);
end;
end.
#include "CreateAFormUnit.hpp"
TForm *f = CreateAForm(__classid(TForm), SomeOwner);
f->ShowModal();
delete f;
Apparently modern Delphi supports metaclasses in much the same way as original Smalltalk.
There is nothing like that in C++.
One main problem with emulating that feature in C++, having run-time dynamic assignment of values that represent type, and being able to create instances from such values, is that in C++ it's necessary to statically know the constructors of a type in order to instantiate.
Probably you can achieve much of the same high-level goal by using C++ static polymorphism, which includes function overloading and the template mechanism, instead of extreme runtime polymorphism with metaclasses.
However, one way to emulate the effect with C++, is to use cloneable exemplar-objects, and/or almost the same idea, polymorphic object factory objects. The former is quite unusual, the latter can be encountered now and then (mostly the difference is where the parameterization occurs: with the examplar-object it's that object's state, while with the object factory it's arguments to the creation function). Personally I would stay away from that, because C++ is designed for static typing, and this idea is about cajoling C++ into emulating a language with very different characteristics and programming style etc.
Type information does not exist at runtime with C++. (Except when enabling RTTI but it is still different than what you need)
A common idiom is to create a virtual clone() method that obviously clones the object which is usually in some prototypical state. It is similar to a constructor, but the concrete type is resolved at runtime.
class Object
{
public:
virtual Object* clone() const = 0;
};
If you don't mind spending some time examining foreign sources, you can take a look at how a project does it: https://github.com/rheit/zdoom/blob/master/src/dobjtype.h (note: this is a quite big and evolving source port of Doom, so be advised even just reading will take quite some time). Look at PClass and related types. I don't know what is done here exactly, but from my limited knowledge they construct a structure with necessary metatable for each class and use some preprocessor magic in form of defines for readability (or something else). Their approach allows seamlessly create usual C++ classes, but adds support for PClass::FindClass("SomeClass") to get the class reference and use that as needed, for example to create an instance of the class. It also can check inheritance, create new classes on the fly and replace classes by others, i. e. you can replace CDoesntWorksUnderWinXP by CWorksEverywhere (as an example, they use it differently of course). I had a quick research back then, their approach isn't exceptional, it was explained on some sites but since I had only so much interest I don't remember details.

What vb6 type is ABI-compatible with std::vector?

I've been writing a DLL in C++, now I must call this DLL from a VB6 application.
Here's a code sample from this DLL :
#include <vector>
#include <string>
using namespace std;
void __stdcall DLLFunction (vector<Object>*)
{
// performs a few operations on the Objects contained in the vector.
}
struct Object
{
long CoordX;
long CoordY;
long Width;
long Height;
LPSTR Id;
};
I also defined the "Object struct" in VB6
Private Type Object
CoordX As Integer
CoordY As Integer
Width As Integer
Height As Integer
Id As String
End Type
The issue is I don't know what vb6 type could stand for std::vector in order to call the DLL's function.
Notes :
- I use a vector for the DLL to be able to add objects.
- I use a pointer in order to use as less memory as possible.
- Sorry for my english, it ain't my home language at all.
- Thank you for reading and trying to help me.
Edit :
- I fixed the typing issues (Ids are definitely ended by NullChar, so LPSTR should do the trick).
- I read your answers, and I'd like to thank both of you, your answers are close to one another and a major issue remains. My DLL definitely needs to add elements to the container. Thus, I'm wondering how I could do the trick. Maybe I could add a return type to my function and then make that the function is able to return the items it created (instead of putting it directly into the container) so that the vb6 application gets these items and is able to process them, but I can't figure out how to do this
Edit bis :
#Rook : I feel like I could achieve this by using a new struct.
struct ObjectArrayPointer
{
Object* Pointer;
size_t Counter;
}
And then call my function this way :
void __stdcall DLLFunction (ObjectArrayPointer*);
I would then be able to add objects and edit the size parameter for my VB6 application to find these new objects. Was that what you meant?
You should not be trying to export template containers from a DLL anyway. They're likely to break when faced with newer compilers and libraries (eg. a library built under C++03 will not play well with code built using C++11).
The least painful thing to do is to accept a pointer to a buffer and a length parameter,
void __stdcall DLLFunction (Object* buffer, size_t nObjects);
if the size of the container will not change during execution. This interface is about as simple as it gets, and is easily accessible by any language that understand C calling conventions (eg. almost every single one.)
You've already thrown away most of the use of a std::vector because you've already specialised it to Object; you could consider going all the way and creating your own ObjectCollection class which uses a std::vector internally but presents a non-templated interface. Here's a simple example :
// In your public API header file:
typedef struct object_collection_t *object_collection;
object_collection CreateObjectCollection();
void DestroyObjectCollect(object_collection collection);
void AddObjectToCollection(object_collection collection, Object* object);
// etc
No template types are exposed in any form in the header. This is good.
// And the corresponding code file:
struct object_collection_t
{
std::vector<Object*> objects;
};
object_collection CreateObjectCollection() { return new object_collection_t; }
void DestroyObjectCollect(object_collection collection) { delete collection; }
void AddObjectToCollection(object_collection collection, Object* object)
{
collection->objects.push_back(object);
}
// etc
All of templating code is hidden away, leaving you with a fairly clean and simple interface which present an opaque pointer type that can be passed around by external code but only queried and modified by your own, etc.
EDIT: Incidentally, I've used Object* throughout the above code. It may well be safer and impler to use just plain old Object and avoid all of the issues associated with memory management and pointer manipulation by client code. If Object is sufficiently small and simple, passing by value may be a better approach.
(NB: not checked for compilability or functionality. E&OE. Caveat Implementor!)
You can't do that as it's a C++ class/template. Internally, it's an array but not in a way that can be created from VB6.
Your best bet is to change the function to accept a pointer to an array with a count parameter.
You'll also need to be very careful as to how the type is structured.
C++ ints are Longs in VB6.
Also, the Id string won't be compatible. VB6 will have a pointer to a unicode BString (unless you make it fixed length) where as a C++ will have std::string which is an array of ANSI chars. VB6 MAY marshal this if you pass an array of the objects (rather than a pointer)
The VB6 ABI is the COM Automation ABI.
Therefore, if you need an arry which is VB6 ABI compatible, you should probably use SAFEARRAY. I suggest you should also be using the Compiler COM Support classes:
http://msdn.microsoft.com/en-US/library/5yb2sfxk(v=vs.80).aspx
This question appears to do exactly what you want, using ATL's CComSafeArray class:
conversion between std::vector and _variant_t
You may also want to look at these:
https://stackoverflow.com/search?q=safearray+_variant_t
Alternatives to SAFEARRAY
The alternative to SAFEARRAY is to supply a COM Collection object. This is simply a COM object with a Dispinterface or Dual interface with the methods Count and Item. Item should have dispid=0 to be the default method. You may also want to supply _NewEnum with DISPID_NEWENUM to support the For Each syntax.

Handles Comparison: empty classes vs. undefined classes vs. void*

Microsoft's GDI+ defines many empty classes to be treated as handles internally. For example, (source GdiPlusGpStubs.h)
//Approach 1
class GpGraphics {};
class GpBrush {};
class GpTexture : public GpBrush {};
class GpSolidFill : public GpBrush {};
class GpLineGradient : public GpBrush {};
class GpPathGradient : public GpBrush {};
class GpHatch : public GpBrush {};
class GpPen {};
class GpCustomLineCap {};
There are other two ways to define handles. They're,
//Approach 2
class BOOK; //no need to define it!
typedef BOOK *PBOOK;
typedef PBOOK HBOOK; //handle to be used internally
//Approach 3
typedef void* PVOID;
typedef PVOID HBOOK; //handle to be used internally
I just want to know the advantages and disadvantages of each of these approaches.
One advantage with Microsoft's approach is that, they can define type-safe hierarchy of handles using empty classes, which (I think) is not possible with the other two approaches, though I wonder what advantages this hierarchy would bring to the implementation? Anyway, what else?
EDIT:
One advantage with the second approach (i.e using incomplete classes) is that we can prevent clients from dereferencing the handles (that means, this approach appears to support encapsulation strongly, I suppose). The code would not even compile if one attempts to dereference handles. What else?
The same advantage one has with third approach as well, that you cannot dereference the handles.
Approach #1 is some mid-way between C style and C++ interface. Instead of member functions you have to pass the handle as argument. The advantage of exposed polymorphism is that you can reduce the amount of functions in interface and the types are checked compile time. Usually most experts prefer pimpl idiom (sometimes called compilation firewall) to such interface. You can not use approach #1 to interface with C so better go full C++.
Approach #2 is C style encapsulation and information hiding. The pointer may be (and often is) a pointer to real thing, so it is not over-engineered. User of library may not dereference that pointer. Disadvantage is that it does not expose any polymorphism. Advantage is that you may use it when interfacing with modules written in C.
Approach #3 is over-abstracted C-style encapsulation. The pointer may be really not a pointer at all since user of library should not cast, deallocate or dereference it. Advantage is that it may so carry exception or error values, disadvantage is that most of it has to be checked run time.
I agree with DeadMG that language-neutral object-oriented interfaces are very easy and elegant to use from C++, but these also involve more run-time checks than compile time checks and are overkill when i don't need to interface with other languages. So i personally prefer Approach #2 if it needs to interface with C or Pimpl idiom when it is C++ only.
2 and 3 are slightly less typesafe as they allow to use handles instead of void*
void bluescreeen(HBOOK hb){
memset(hb,0,100000); // no compile errors
}
Approach 3 is not very good at all, as it allows the mixing and matching of handle types that don't actually make sense, any function that takes a HANDLE can take any HANDLE, even if it's compile-time determinable that that is the wrong type.
The downside of Approach 1 is that you have to do a bunch of casting on the other end to their actual types.
Approach 2 isn't that bad, except you can't do any kind of inheritance with it without having to externally query every time.
However, all of this is entirely moot ever since compilers discovered how to implement efficient virtual functions. The approach taken by DirectX and COM is the best- it's very flexible, powerful, and completely type-safe.
It even allows for some truly insane things, like you can inherit from DirectX interfaces and extend it that way. One of the best advantages of this is Direct2D and Direct3D11. They're not actually compatible (which is truly, horrendously stupid), but you can define a proxy type that inherits from ID3D10Device1 and forwards to the ID3D11Device and solve the problem like that. That kind of thing would never even think about being possible with any of the above approaches.
Oh, and last thing: You really, really shouldn't name your types in allcaps.

Achieving Interface functionality in C++

A big reason why I use OOP is to create code that is easily reusable. For that purpose Java style interfaces are perfect. However, when dealing with C++ I really can't achieve any sort of functionality like interfaces... at least not with ease.
I know about pure virtual base classes, but what really ticks me off is that they force me into really awkward code with pointers. E.g. map<int, Node*> nodes; (where Node is the virtual base class).
This is sometimes ok, but sometimes pointers to base classes are just not a possible solution. E.g. if you want to return an object packaged as an interface you would have to return a base-class-casted pointer to the object.. but that object is on the stack and won't be there after the pointer is returned. Of course you could start using the heap extensively to avoid this but that's adding so much more work than there should be (avoiding memory leaks).
Is there any way to achieve interface-like functionality in C++ without have to awkwardly deal with pointers and the heap?? (Honestly for all that trouble and awkardness id rather just stick with C.)
You can use boost::shared_ptr<T> to avoid the raw pointers. As a side note, the reason why you don't see a pointer in the Java syntax has nothing to do with how C++ implements interfaces vs. how Java implements interfaces, but rather it is the result of the fact that all objects in Java are implicit pointers (the * is hidden).
Template MetaProgramming is a pretty cool thing. The basic idea? "Compile time polymorphism and implicit interfaces", Effective C++. Basically you can get the interfaces you want via templated classes. A VERY simple example:
template <class T>
bool foo( const T& _object )
{
if ( _object != _someStupidObject && _object > 0 )
return true;
return false;
}
So in the above code what can we say about the object T? Well it must be compatible with '_someStupidObject' OR it must be convertible to a type which is compatible. It must be comparable with an integral value, or again convertible to a type which is. So we have now defined an interface for the class T. The book "Effective C++" offers a much better and more detailed explanation. Hopefully the above code gives you some idea of the "interface" capability of templates. Also have a look at pretty much any of the boost libraries they are almost all chalk full of templatization.
Considering C++ doesn't require generic parameter constraints like C#, then if you can get away with it you can use boost::concept_check. Of course, this only works in limited situations, but if you can use it as your solution then you'll certainly have faster code with smaller objects (less vtable overhead).
Dynamic dispatch that uses vtables (for example, pure virtual bases) will make your objects grow in size as they implement more interfaces. Managed languages do not suffer from this problem (this is a .NET link, but Java is similar).
I think the answer to your question is no - there is no easier way. If you want pure interfaces (well, as pure as you can get in C++), you're going to have to put up with all the heap management (or try using a garbage collector. There are other questions on that topic, but my opinion on the subject is that if you want a garbage collector, use a language designed with one. Like Java).
One big way to ease your heap management pain somewhat is auto pointers. Boost has a nice automatic pointer that does a lot of heap management work for you. The std::auto_ptr works, but it's quite quirky in my opinion.
You might also evaluate whether you really need those pure interfaces or not. Sometimes you do, but sometimes (like some of the code I work with), the pure interfaces are only ever instantiated by one class, and thus just become extra work, with no benefit to the end product.
While auto_ptr has some weird rules of use that you must know*, it exists to make this kind of thing work easily.
auto_ptr<Base> getMeAThing() {
return new Derived();
}
void something() {
auto_ptr<Base> myThing = getMeAThing();
myThing->foo(); // Calls Derived::foo, if virtual
// The Derived object will be deleted on exit to this function.
}
*Never put auto_ptrs in containers, for one. Understand what they do on assignment is another.
This is actually one of the cases in which C++ shines. The fact that C++ provides templates and functions that are not bound to a class makes reuse much easier than in pure object oriented languages. The reality though is that you will have to adjust they manner in which you write your code in order to make use of these benefits. People that come from pure OO languages often have difficulty with this, but in C++ an objects interface includes not member functions. In fact it is considered to be good practice in C++ to use non-member functions to implement an objects interface whenever possible. Once you get the hang of using template nonmember functions to implement interfaces, well it is a somewhat life changing experience. \