typedef problem

Started by
1 comment, last by Alex Melbourne 11 years, 4 months ago
Please excuse my lack of knowledge but I never worked with typedefs too much.Here's the code:

[source lang="cpp"]extern "C" {
HRESULT CreateRenderDevice(HINSTANCE hDLL, ZFXRenderDevice **pInterface);
typedef HRESULT (*CREATERENDERDEVICE)(HINSTANCE hDLL, ZFXRenderDevice **pInterface);

HRESULT ReleaseRenderDevice(ZFXRenderDevice **pInterface);
typedef HRESULT (*RELEASERENDERDEVICE)(ZFXRenderDevice **pInterface);
}[/source]

Now you probably know that this is static & dynamic library releated.

What I don't understand is:
typedef HRESULT (*CREATERENDERDEVICE)(HINSTANCE hDLL, ZFXRenderDevice **pInterface);

so what does this mean? (*CREATERENDERDEVICE)(HINSTANCE hDLL, ZFXRenderDevice **pInterface) is it a cast or...?
Also we used typedef for what? does this (*CREATERENDERDEVICE)(HINSTANCE hDLL, ZFXRenderDevice **pInterface) refer to a HRESULT now?

The release function from the above code is used later like this:

_ReleaseRenderDevice = (RELEASERENDERDEVICE)
GetProcAddress(m_hDLL, "ReleaseRenderDevice");

From the 2 lines above I understand that the returned object from GetProcAddress(m_hDLL, "ReleaseRenderDevice") is casted to RELEASERENDERDEVICE.



Please,some explanations? In the book it doesn't explain too much about dlls and static libraries,knowledge about them is a assumed.
Advertisement
Those are function pointer typedefs. To make a typedef for a function pointer you first write a function declaration with the typedef name as the function name then stick a * in front of the typedef name and wrap that in parenthesis and stick the word typedef in front of the whole thing. So let's say you were going to make a typedef named foo for a function pointer taking an int and returning an int. So the steps would look like:

int foo(int);
int (*foo)(int);
typedef int (*foo)(int);

Once you have the function pointer typedefs, you can cast pointers you get from GetProcAddress() to those function pointer types and then call them like functions.
'typedef' is considered grammatically as storage class. It aliases types (it does not create new types).

C/C++'s grammar is, at least in my opinion, beautiful because everything can be reduced to the same make-up:[source lang="cpp"][type-qualifier] [storage class] type-specifier declarator [= initializer];[/source]Where 'declarator' is:[source lang="cpp"][type-modifier] identifier[/source]There's a few subtlies I fail to capture there but I recommend reading about it.

Anyway, a type-modifier is like a pointer or a function call. But each type-modifier can be place inside another recursively this means you can build a theoretically infinitely deep type.

The issue is that the operators bind slightly differently. But you can use parentheses to force certain 'alignment' (just like you can in normal expressions.

This means that while:[source lang="cpp"]char *fn(void)[/source]is a function returning a pointer to a character (because the function-type modifier binds more tightly than the pointer modifier)[source lang="cpp"]char (*fn)(void)[/source]is a pointer to a function that takes no arguments and returns a single character.

Using 'typedef' as the storage class means that the identifier becomes an alias for the type you have just created. So:[source lang="cpp"]typedef char (*fn)(void)[/source] aliases a new type 'fn' that can be used to specify when a pointer to a function taking no arguments and returning a character is required.

This technique is used extensively for callbacks and often in COM (which I imply from the code you've presented).

Just remember that identifiers aren't allowed to gain 'function status' through type-defines. That is you can't do:[source lang="cpp"]typedef char *fn(void)
fn a, b, c;[/source]

This topic is closed to new replies.

Advertisement