Dixon Steel
Dixon Steel

Reputation: 1061

How to make a void** point to a function?

I have code that looks like this:

extern "C" __declspec(dllexport)  myInterface(int id, void** pFunction)
{
   ...
}

I need to make the void** pFunction argument point to a function so that the caller can use this function via the pFunction pointer. This function gets called through a DLL, I don't want to do it this way but for a lot of reasons I have no choice. I know that COM is made for this but I can not use it, the reasons come down to management.

At this point I have no idea how to do this, everything I have tried to do gives me cast problems. Do anyone have any idea how I can do this? I can post more if this is unclear.

Thanks.

Upvotes: 0

Views: 508

Answers (5)

Dixon Steel
Dixon Steel

Reputation: 1061

I want to thank everyone for help. Here is how I get it to work at least in part. Basically the wrapper idea works.

struct myProj { virtual HRESULT __stdcall myMethod(unsigned short* & myname); };

HRESULT __stdcall myMethod(unsigned short* & myname) { myname = L"myname";

return(1); }

struct myProj xProject;

To call it:

extern "C" HRESULT __declspec(dllexport) fInterface(UINT id, LPVOID * pObj) { switch(id) { case FVI_ID: *pObj = &xProject; break; } }

This does call the correct function, but it still has it's problems. The third party DLL uses CStrings and I suspect they are giving my other problems as well as some trace functions they contain.

I believe my real solution is I can't fake out the com, that we need to realize the DLL's can not be used in our project.

Thanks everyone.

Upvotes: 0

jamesdlin
jamesdlin

Reputation: 89975

As Jonathan Leffler and David Thornley mentioned, you aren't guaranteed that a function pointer can be converted to void* and back. A portable workaround would be to package the function pointer into a struct and to pass a pointer to that.

(Be aware that void** itself might have its own issues. You can avoid this too.)

For example:

typedef int (*SomeFuncType)(int);

struct FuncWrapper
{
    SomeFuncType func;
    void* output;
};

...
FuncWrapper funcWrapper;
funcWrapper.func = ...;

myInterface(id, &funcWrapper);

and then myInterface could be implemented as:

void myInterface(int id, FuncWrapper* funcWrapper)
{
    funcWrapper->func(...);
    funcWrapper->output = ...;
}

Upvotes: 1

ssube
ssube

Reputation: 48267

It's tricksy, but I've had good luck with code like so:

*reinterpret_cast<void**>( &(PVOID&)( DetourFunc ) ) = (PVOID) 0x00FFFF00; 

The concept, as I understand it, is you're referencing a reference, reinterpreting the reference, then dereferencing it. Bit confusing, but I can verify it works. You can also put an address on the right side (&func) and it'll work. Calling DetourFunc, using the form:

(DetourFunc)(param, param)

will call the original address or function.

Edit: This works, but it seems like a pretty heavy abuse of the language. It does work, though, and has been recommended in a few other questions here.

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 753765

If you are looking at the implementation of 'myInterface', then you might be wanting:

switch (id)
{
case FUNC_1:
    *pFunction = (void *)first_function;
    break;
...
}

If you are trying to call the function and pass in a pointer to function, then:

void *vp = (void *)the_function_to_pass;
myInterface(1, &vp);

If you have something else in mind, you need to specify what.

(Note that strictly, C does not guarantee that function pointers can be assigned to object pointers and vice versa. However, POSIX does make that guarantee for you. I believe similar comments apply to C++.)

Upvotes: 3

David Thornley
David Thornley

Reputation: 57036

This is not something that can be done in standard C or C++. There is no guarantee that a function pointer can fit into a void pointer (C++ member function pointers typically can't). In other words, if you can't change the function signature, you can't do what you want in standard C or C++, and there's no guarantee you can do it at all.

Therefore, any solution would be a platform-specific one. You don't specify a platform directly in question or tag, but my guess would be Visual C++ from other things.

Please specify your platform specifically, and anything useful about the function pointer you want to pass.

Upvotes: 1

Related Questions