2013-01-21 12 views
6

Sto provando a chiamare alcune funzioni da Kernel32.dll nel mio script Python in esecuzione su Linux. Come ha indicato Johannes Weiß How to call Wine dll from python on Linux? Sto caricando la libreria kernel32.dll.so tramite ctypes.cdll.LoadLibrary() e carica benissimo. Posso vedere kernel32 caricato e ha anche la funzione GetLastError() all'interno. Tuttavia, ogni volta che cerco di chiamare la funzione sto diventando segfault.Segfault su chiamata windows standard dll da tipi di python con wine

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 

Prima stavo pensando di chiamare differenze convention ma sembra di essere a posto, dopo tutto. Sto terminando con la semplice funzione GetLastError di test senza parametri, ma sto ancora ricevendo comunque un errore di segmentazione.

Il mio sistema di test è Ubuntu 12.10, Python 2.7.3 e vino-1.4.1 (tutto è a 32 bit)

UPD

procedo con il mio test e trovare diverse funzioni che posso chiamare via ctypes senza segfault. Ad esempio, posso dare un nome alle funzioni Beep() e GetCurrentThread(), molte altre funzioni mi danno comunque un segfault. Ho creato una piccola applicazione C per testare la libreria kernel32.dll.so senza python ma ho essenzialmente gli stessi risultati.

Stavo cercando di utilizzare diverse convenzioni di chiamata per la funzione Sleep() ma non ho avuto fortuna anche con esso. Quando mi si confrontano dichiarazioni di funzione \ implementazione nelle fonti di vino sono essenzialmente gli stessi

dichiarazioni

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 

Tuttavia alcuni di loro lavora e alcuni non lo fanno. Come posso capire queste fonti sono per il file kernel32.dll e il file kernel32.dll.so è una sorta di proxy che dovrebbe fornire l'accesso a kernel32.dll per il codice di Linux. Probabilmente ho bisogno di trovare le fonti esatte del file kernel32.dll.so e dare un'occhiata alle dichiarazioni.

C'è qualche strumento che posso usare per dare un'occhiata all'interno del file .so e scoprire quali funzioni e quali convenzioni di chiamata vengono utilizzate?

+0

Non ho familiarità con Wine, ma credo che questo problema abbia a che fare con le convenzioni di chiamata, http://en.wikipedia.org/wiki/X86_calling_conventions, per queste funzioni. La maggior parte di 'kernel32.dll' usa' stdcall'.Puoi provare a chiamare alcune funzioni da 'msvcrt.dll' o' ws2_32.dll', la maggior parte delle sue funzioni usano 'cdecl', non otterrai il segfault. Guarda qui, http://codepad.org/DzX33DYz. –

+0

@Sp. Grazie, ho trovato alcune funzioni che posso chiamare da kernel32.dll.so me stesso. Tuttavia non riesco a trovare alcuna differenza tra loro e le funzioni di cui ho bisogno nel mio codice. Potresti suggerirmi qualche strumento per scoprire le convenzioni di chiamata per la funzione all'interno del file .so? –

+0

Io uso IDA pro, è molto utile per questo lavoro. –

risposta

0

Il modo più semplice per esaminare una DLL è quello di utilizzare il comando nm, vale a dire

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

Come altri hanno fatto notare, la convenzione di chiamata predefinito per Windows C DLL è stdcall. Non ha nulla a che fare con l'utilizzo di Python. Sulla piattaforma Windows, è disponibile ctypes.windll.

Tuttavia, Non sono nemmeno sicuro che quello che si sta tentando di fare è possibile. Wine è un emulatore di Windows in piena regola ed è sicuro che almeno avresti dovuto avviarlo con wine_init prima di caricare qualsiasi altra funzione. L'API di Windows probabilmente ha uno stato (impostato all'avvio di Windows).

Il modo più semplice per continuare è probabilmente installare una versione di Python per Windows in Wine ed eseguire lo script da lì.