7

Basically I'm wondering if there is a way using Wine (libwine maybe?) to make a wrapper .so for a windows .dll. Something where I load the .dll, load a few function pointers from it, and use Wine like an FFI. It seems like Wine must have to do this internally, constantly calling back and forth from the System V ABI and the Windows one.

Specifically I have an interface library for an expensive scientific data logging device that communicates over UDP and not directly to the HW. The API itself is only about 20 functions long using simple types (ints, doubles, double[]) so making a wrapper .so by hand wouldn't be all that much work if it is indeed possible.

edit: I made some partial progress, but not a solution. I did some reading and found out about winegcc. I knew libSDL had a fairly straight forward log function, so I got a windows .dll of it and did the following:

HINSTANCE sdl = LoadLibrary("SDL2.dll");
assert(sdl);

typedef void logf(const char* fmt, ...);
logf *log = (logf*)GetProcAddress(sdl, "SDL_Log");
assert(log);

log("Hello");

It sort of works! It prints out "INFO: ??{" to the console, so the function pointer is being retrieved correctly and since it prints anything at all the dll must be calling back into libwine correctly. I was kind of hoping that GetProcAddress() would return a magic trampoline that converts the ABI for me, but maybe that's not the case? If I call the log function using inline assembly to pass the parameters using the MS ABI, it still does the same thing, so I'm not really sure what to try next.

slembcke
  • 1,359
  • 7
  • 7

1 Answers1

2

Augh! I was so close. Posting the solution since it took a few days of digging to figure out.

I just needed to add the "WINAPI" qualifier to the function declaration. If all it's doing is setting the calling convention, I'm not sure why my assembly version didn't work, but whatever. The following code successfully opens a window on Linux using the windows SDL2.dll for example.

HINSTANCE sdl = LoadLibrary("SDL2.dll");
assert(sdl);

WINAPI __typeof(SDL_Init)* init = GetProcAddress(sdl, "SDL_Init");
err = init(SDL_INIT_VIDEO);
assert(err == 0);

WINAPI __typeof(SDL_CreateWindow)* create_window = GetProcAddress(sdl, "SDL_CreateWindow");
SDL_Window* window = create_window("Drift", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1024, 768, 0);
assert(window);

WINAPI __typeof(SDL_Delay)* delay = GetProcAddress(sdl, "SDL_Delay");
delay(3000);
slembcke
  • 1,359
  • 7
  • 7
  • And what is the reason to use Wine instead of actually Windows? :) – Michael Chourdakis Jul 21 '19 at 22:03
  • 1
    Irrelevant to the question, but moving the rest of the workflow to Windows would be more initial work, and more constant hassle than simply rebooting once in a while or using a second computer to collect data. – slembcke Jul 23 '19 at 15:09
  • I've tried to do similar thing. My goal was to run only wrapped windows dll in wine and everything else would be compiled and ran as normal linux process. After couple of days of experimenting I came to conclusion that if wine wrapper is to be linked, then the whole app will have to be compiled using winegcc/winec++ and executed using wine. @slembcke have you managed to link wrapper without winetools? – alex Nov 25 '21 at 19:57
  • @alex Kinda sorta yes. What I ended up doing was to make a trivial wine executable and used shared memory to communicate to my actual native linux executable that did the realtime stuff. This worked fine since the DLL was _really_ simple (and thus why I didn't want to move _everything_ to Windows just for one dinky little DLL.) If it was more complicated I'd bet you could use some sort of RPC or FFI lib to make it work easily too. (shrug) – slembcke Dec 03 '21 at 21:36
  • My goal was to use proper dev env to conveniently debug code. With wine that was a major issue at first. Tried to use [rpclib](https://github.com/rpclib/rpclib) to wrap a win32 library but library calls callbacks from a separate thread, so two way rcp would be required - too complex. So eventually I changed my setup so that I could develop and debug my code running on wine. [Here is a boilerplate project](https://github.com/aleksas/vscode-wine-mingw-boilerplate). – alex Jun 15 '22 at 09:42