Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrap Windows dll using Wine on Linux

Tags:

wine

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.

like image 590
slembcke Avatar asked Jul 19 '19 22:07

slembcke


People also ask

Can Windows DLL be used in Linux?

Any solution is going to need a TCP/IP-based "remoting" layer between the DLL which is running in a "windows-like" environment, and your linux app. You'll need to write a simple PC app to expose the DLL functions, either using a homebrew protocol, or maybe XML-RPC, SOAP or JSON protocols.

Can you make a DLL in Linux?

You need to use command called dlltool. It create files needed to build and use DLLs. dlltool reads its inputs, which can come from the -d and -b options as well as object files specified on the command line.

Where does wine look DLL?

On a Windows system, system libraries are installed into C:\windows\system32 (and C:\windows\syswow64 for 32-bit DLLs on a 64-bit system). Wine also installs DLLs into this directory. Some applications actually open these files directly and expect them to be valid Windows DLLs.

What is DLL in Linux?

An external software module used by the Linux operating system. The official name for this type of module is a "shared object" or "shared library," but due to the universal embrace of Windows, which uses DLLs, the DLL term occasionally creeps into Linux lingo.


1 Answers

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);
like image 63
slembcke Avatar answered Oct 17 '22 07:10

slembcke