【发布时间】:2017-05-01 18:37:09
【问题描述】:
我有一个名为morag.dll 的Windows DLL,其中包含函数foo 和bar。我还有一个名为 morag.so 的 Linux SO,其中包含 foo 和 bar 的 Linux 实现(每个平台上的参数相同)。我有一个加载morag.dll 的Windows 应用程序,我想在wine 下运行它。应用程序本身运行良好,但是我需要创建 foo 和 bar 之间的映射,这是我的应用程序期望在 morag.dll 中找到的,而不是在 morag.so 中使用 foo 和 bar。
为此,我知道我需要创建morag.dll.spec 文件并将其winebuild 到morag.dll.so。
按照here 的说明,我在morag.c 中创建了一个包装器,其中包含函数Proxyfoo 和Proxybar,它们只不过是调用真正的函数foo 和bar。然后我创建了morag.dll.spec 这样:-
1 stdcall foo (long ptr) Proxyfoo
2 stdcall bar (ptr ptr) Proxybar
我编译了我的c部分,winebuild了spec文件,然后使用winegcc将它们链接到morag.dll.so
然后我读到了this page,这表明您可能不需要代理功能,所以我尝试完全不使用 c 部分并制作了一个规范文件:-
1 stdcall foo (long ptr)
2 stdcall bar (ptr ptr)
和上面一样,做了 winebuild 步骤和 winegcc 链接步骤。
在这两种情况下,这些都是我使用的选项。
winebuild --dll -m32 -E ./morag.dll.spec -o morag.dll.o
ldopts= -m32 -fPIC -shared -L/usr/lib/wine -L/opt/morag/lib -lmorag
winegcc $(ldopts) -z muldefs -o morag.dll.so [morag.o] morag.dll.o
注意[..] 表示我只在构建 c 部分的情况下使用它。
在这两种情况下,当我在 wine 下运行的应用程序尝试使用 GetProcAddress 加载 DLL 中的入口点时,它都会失败。
我用WINEDEBUG=+module,+relay运行wine,看到尝试和失败记录如下:-
0025:Ret KERNEL32.LoadLibraryExA() retval=7dbc0000 ret=00447b84
0025:Call KERNEL32.GetProcAddress(7dbc0000,00b2d060 "foo") ret=00447c8a
0025:Ret KERNEL32.GetProcAddress() retval=00000000 ret=00447c8a
它似乎已经找到并加载了我的 morag.dll.so,因为 LoadLibraryExA 已将句柄返回给它,但是当它尝试在该 HMODULE 句柄中查找函数 foo 时它失败了。
如果我发出:-
nm -D morag.dll.so
我看到 foo 和 bar 在这两种情况下都显示为 U。也有代理函数的情况下,代理函数显示为T。
我认为这是因为我没有正确构建morag.dll.so 文件,或者使用了错误的选项,或者我的规范文件格式不正确。我不确定应该使用上述两种方案中的哪一种。
非常感谢所有帮助。
【问题讨论】: