簡體   English   中英

Segfault調用標准windows .dll從python ctypes與wine

[英]Segfault on calling standard windows .dll from python ctypes with wine

我正試圖在我在Linux上運行的Python腳本中調用Kernel32.dll中的某些函數。 正如JohannesWeiß所指出的如何在Linux上從python調用Wine dll? 我正在通過ctypes.cdll.LoadLibrary()加載kernel32.dll.so庫並且加載正常。 我可以看到kernel32加載,甚至里面有GetLastError()函數。 但是每當我試圖調用該函數時,我都會遇到段錯誤。

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函數沒有任何參數,但我仍然得到Segmentation故障。

我的測試系統是Ubuntu 12.10,Python 2.7.3和wine-1.4.1(一切都是32位)

UPD

我繼續我的測試,並找到幾個我可以通過ctypes調用而沒有segfault的函數。 例如,我可以命名Beep()和GetCurrentThread()函數,許多其他函數仍然給我segfault。 我創建了一個小的C應用程序來測試沒有python的kernel32.dll.so庫,但我得到了基本相同的結果。

int main(int argc, char **argv) 
{

   void *lib_handle;

   #define LOAD_LIBRARY_AS_DATAFILE            0x00000002

   long (*GetCurrentThread)(void);
   long (*beep)(long,long);
   void (*sleep)(long);   
   long (*LoadLibraryExA)(char*, long, long);


   long x;
   char *error;

   lib_handle = dlopen("/usr/local/lib/wine/kernel32.dll.so", RTLD_LAZY);

   if (!lib_handle) 
   {
      fprintf(stderr, "%s\n", dlerror());
      exit(1);
   }

   // All the functions are loaded e.g. sleep != NULL
   GetCurrentThread = dlsym(lib_handle, "GetCurrentThread");
   beep = dlsym(lib_handle, "Beep");
   LoadLibraryExA = dlsym(lib_handle, "LoadLibraryExA");
   sleep = dlsym(lib_handle, "Sleep");




   if ((error = dlerror()) != NULL)  
   {
      fprintf(stderr, "%s\n", error);
      exit(1);
   }

   // Works
   x = (*GetCurrentThread)();   
   printf("Val x=%d\n",x);

   // Works (no beeping, but no segfault too)
   (*beep)(500,500);    

   // Segfault  
   (*sleep)(5000);      

   // Segfault  
   (*LoadLibraryExA)("/home/ubuntu/test.dll",0,LOAD_LIBRARY_AS_DATAFILE);


   printf("The End\n");
   dlclose(lib_handle);
   return 0;
}

我試圖為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.dll.so文件是某種代理,它應該為linux代碼提供對kernel32.dll的訪問。 可能我需要找到kernel32.dll.so文件的確切來源並查看聲明。

是否有任何工具可以用來查看.so文件,找出哪些函數和使用的調用約定?

檢查DLL的最簡單方法是使用nm命令,即

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

正如其他人所指出的,Windows C DLL的默認調用約定是stdcall 它與使用Python無關。 在Windows平台上,可以使用ctypes.windll

但是, 我甚至不確定你想要做什么 Wine是一個成熟的Windows模擬器,可以安全地猜測,至少你必須在加載任何其他函數之前用wine_init啟動它。 Windows API可能具有某種狀態(在Windows啟動時設置)。

最簡單的方法是在Wine下安裝Windows版本的Python並從那里運行腳本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM