用win从python ctypes调用标准windows.dll的Segfault

2024-09-27 04:29:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在Linux上运行的Python脚本中从Kernel32.dll调用一些函数。正如Johannes Weiß指出的How to call Wine dll from python on Linux?我正在加载内核32。动态链接库.so通过ctypes.cdll.LoadLibrary()而且装得很好。我可以看到kernel32已加载,甚至还有GetLastError()函数。不过,每当我试图调用函数时,都会得到segfault。在

import ctypes

kernel32 = ctypes.cdll.LoadLibrary('/usr/lib/i386-linux-gnu/wine/kernel32.dll.so')

print kernel32
# <CDLL '/usr/lib/i386-linux-gnu/wine/kernel32.dll.so', handle 8843c10 at b7412e8c>

print kernel32.GetLastError
# <_FuncPtr object at 0xb740b094>

gle = kernel32.GetLastError
# OK

gle_result = gle()
# fails with
# Segmentation fault (core dumped)

print gle_result

首先,我想称之为惯例差异,但似乎没什么大不了的。我以测试简单函数GetLastError函数结束,没有任何参数,但我仍然得到分段错误。在

我的测试系统是Ubuntu12.10、Python2.7.3和wine-1.4.1(一切都是32位)

升级版

我继续我的测试,找到了几个函数,我可以通过ctypes调用而不使用segfault。例如,我可以命名Beep()和GetCurrentThread()函数,许多其他函数仍然给我segfault。我创建了一个小的C应用程序来测试kernel32。动态链接库.so库中没有python,但我得到的结果基本上是相同的。在

^{pr2}$

我试图对Sleep()函数使用不同的调用约定,但也没有成功。当我比较Wine源代码中的函数声明\实现时,它们本质上是相同的

声明

 HANDLE WINAPI GetCurrentThread(void) // http://source.winehq.org/source/dlls/kernel32/thread.c#L573
 BOOL WINAPI Beep( DWORD dwFreq, DWORD dwDur ) // http://source.winehq.org/source/dlls/kernel32/console.c#L354
 HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags) // http://source.winehq.org/source/dlls/kernel32/module.c#L928
 VOID WINAPI DECLSPEC_HOTPATCH Sleep( DWORD timeout ) // http://source.winehq.org/source/dlls/kernel32/sync.c#L95

 WINAPI is defined to be __stdcall 

不过,有些是有用的,有些是不行的。据我所知,这些源代码是针对kernel32.dll文件和kernel32的。动态链接库.so文件是一种代理,它应该提供对kernel32.dll for linux代码的访问。也许我需要找到kernel32的确切来源。动态链接库.so归档并查看声明。在

有没有什么工具可以让我看一下里面的.所以文件并找出使用了什么函数和什么调用约定?在


Tags: 函数orghttpsourcesoctypesdllsegfault
1条回答
网友
1楼 · 发布于 2024-09-27 04:29:14

检查DLL的最简单方法是使用nm命令,即

$ nm kernel32.dll.so | grep GetLastError
7b86aae0 T _GetLastError

正如其他人所指出的,windowscdll的默认调用约定是stdcall。它与使用Python无关。在Windows平台上,ctypes.windll可用。在

但是,我甚至不确定您要做的事情是否可能。Wine是一个成熟的Windows仿真器,可以肯定的是,在加载任何其他函数之前,至少必须从wine_init开始。Windows API可能有某种状态(在Windows启动时设置)。在

继续的最简单方法可能是在Wine下安装一个Windows版本的Python,然后从那里运行脚本。在

相关问题 更多 >

    热门问题