在 Linux 上使用 Wine 封装 Windows dll

sle*_*cke 7 wine

基本上我想知道是否有一种方法使用 Wine (也许是 libwine?) 为 windows .dll 制作包装器 .so 。我加载 .dll,从中加载一些函数指针,然后像 FFI 一样使用 Wine。看来 Wine 必须在内部执行此操作,不断地从 System V ABI 和 Windows ABI 来回调用。

具体来说,我有一个用于昂贵的科学数据记录设备的接口库,该设备通过 UDP 进行通信,而不是直接与硬件进行通信。API 本身只有大约 20 个使用简单类型(int、double、double[])的函数,因此如果确实可能的话,手动制作包装器 .so 就不会做那么多工作。

编辑:我取得了一些部分进展,但不是解决方案。我做了一些阅读并发现了 winegcc。我知道 libSDL 有一个相当简单的日志函数,所以我得到了它的 windows .dll 并执行了以下操作:

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

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

log("Hello");
Run Code Online (Sandbox Code Playgroud)

有点效果!它向控制台打印出“INFO: ??{”,因此函数指针被正确检索,并且由于它打印任何内容,因此 dll 必须正确回调到 libwine。我有点希望 GetProcAddress() 会返回一个神奇的蹦床来为我转换 ABI,但也许情况并非如此?如果我使用内联汇编调用日志函数以使用 MS ABI 传递参数,它仍然会执行相同的操作,因此我不太确定下一步要尝试什么。

sle*_*cke 2

啊啊!我是如此接近。发布解决方案,因为花了几天的时间才弄清楚。

我只需要将“WINAPI”限定符添加到函数声明中。如果它所做的只是设置调用约定,我不确定为什么我的程序集版本不起作用,但无论如何。例如,以下代码使用 Windows SDL2.dll 在 Linux 上成功打开一个窗口。

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);
Run Code Online (Sandbox Code Playgroud)