Morag Hughson
Morag Hughson

Reputation: 7579

Callback function pointers in wine

TL;DR; Is it possible, under wine, to call a function in a Windows exe, by function pointer, from the Linux proxy library?

I have a Windows x64 DLL called morag.dll containing a function foo. I also have a Linux SO called morag.so containing the Linux implementation of foo (same parameters on each platform). I have a Windows application that loads morag.dll that I want to run under wine. I have created the mapping between Windows foo and Linux foo by creating a morag.dll.spec file, and a proxy wrapper and building this using winegcc.

morag.dll.spec contains:-

1 cdecl foo (ptr ptr) Proxyfoo

morag.c contains:-

#include <windef.h>
#include <FOO.h>                /* def of FOOSTRUCT */
void WINAPI Proxyfoo (long * parm1, FOOSTRUCT * parm2)
{
  foo(parm1, parm2);
}

Build command:-

winegcc -m64 -fPIC -d_WIN64=1 -I various-includes -z muldefs morag.c morag.dll.spec -o morag.dll.so -shared -L various-libraries -lfoo

This works well. I can successfully call foo from my Windows application and invoke foo in the Linux implementation.

The issue I am facing is when foo is a function that is given a callback function pointer to run later. Clearly the Windows application that calls foo provides it with a function pointer using Windows x64 conventions, but the Linux implementation of foo is invoking the function pointer under the assumption it is using Linux x64 conventions. So unsurprisingly, it fails.

To try to fix this I have attempted, in the proxy layer coded in morag.c to switch out the function pointer with one that meets Linux x64 conventions, and then when it is called back, drive the originally provided function pointer from the proxy layer with Windows x64 conventions.

So now, morag.c contains:-

#include <windef.h>
#include <FOO.h>                /* def of FOOSTRUCT */

typedef void (WINAPI * CBFN)(long * cbparm);

static CBFN SavedCallbackFn;

void ProxyCallbackFn(long * cbparm)
{
  SavedCallbackFn(cbparm);
}
void WINAPI Proxyfoo (long * parm1, FOOSTRUCT * parm2)
{
  SavedCallbackFn = parm2->CallbackFn;
  parm2->CallbackFn = ProxyCallbackFn;
  foo(parm1, parm2);
}

However, this does not work. The ProxyCallbackFn is successfully called by the Linux implementation of foo, but my call to SavedCallbackFn causes SIGSEGV. I had thought that the "trick" needed was simply to get WINAPI onto the function definition.

In other words is it possible to call a function in the Windows exe, by function pointer, from the Linux proxy library?

What am I missing?

Upvotes: 0

Views: 80

Answers (0)

Related Questions