Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The right type for handles in C interfaces

Tags:

c++

c

api

I'm creating a C api that hides some functionality in a DLL file.

Since everything is C++ on the inside most of the functions works against handles which maps directly to this pointers on the inside of the API.

To get a some degree of type safety for those handles I define them like this:

typedef struct MyType1* MyType1Handle;
typedef struct MyType2* MyType2Handle;

I don't actually define MyType1 or MyType2 at any place since I only use them as pointers and do a type cast on the inside of the api to the actual pointer type.

My problem is that when using my library in a clr project in visual studio I get this warning: unresolved typeref token (token) for 'type'; image may not run.

http://msdn.microsoft.com/en-us/library/h8027ys9(VS.80).aspx

It's no big deal since it works, but it looks unprofessional.

I don't like using void*:

typedef void* MyType1Handle;
typedef void* MyType2Handle;

This makes it possible to call a function wanting a MyType1Handle with a MyType2Handle since they are actually the same type.

Another approach I don't want to use is something like this

typedef int MyType1Handle;
typedef int MyType2Handle;

This would work fine as long as int's and pointers have the same size, but that's not always the case and it seems like there is no foolproof way of getting a platform specific pointer sized integer. It has the same type safety problems as the void* as well.

Another approach I tried was to do it like this:

struct MyType1{};
typedef struct MyType1* MyType1Handle;

This didn't work in C since empty structs is invalid C code. I could of course extend my struct with a dummy member, but it seems like there should be a better way of doing this.

So my question boils down to:

How do you generally specify this kind of types in the most compatible way?

like image 613
Laserallan Avatar asked May 08 '09 13:05

Laserallan


1 Answers

If you look at how Microsoft defines it's winapi handles (winnt.h) it actually looks like this:

struct HWND__ { int unused; }; typedef struct HWND__ *HWND

in fact they have a macro for this:

#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name

so.. this seems to be a common practice to do so. Unfortunately I can't make another suggestion except this one, which you already mentioned, but I hope it helps you anyway.

like image 102
lx. Avatar answered Sep 25 '22 19:09

lx.