Próbuję wywołać jakąś funkcję z Kernel32.dll w moim skrypcie Pythona działającym pod Linuksem. Jak Johannes Weiß wskazał How to call Wine dll from python on Linux? ładuję bibliotekę kernel32.dll.so przez ctypes.cdll.LoadLibrary() i ładuje się dobrze. Widzę załadowany kernel32, a nawet ma wewnątrz funkcję GetLastError(). Jednak za każdym razem, gdy próbuję wywołać funkcję I'm gettings segfault.Segfault na wywołanie standardowego okna .dll z python ctypes z winem
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
Najpierw myślałem o wywołaniu różnic w konwencjach, ale mimo wszystko wydaje się być w porządku. Kończę testowaniem prostej funkcji GetLastError bez żadnych parametrów, ale i tak nadal otrzymuję błąd Segmentacji.
moim systemie testowym jest Ubuntu 12.10, Python 2.7.3 i 1.4.1 wina (wszystko jest 32bit)
UPD
mogę kontynuować moje badania i znaleźć kilka funkcji, które mogę nazwać za pośrednictwem ctypes bez segfault. Na przykład mogę wymienić funkcje Beep() i GetCurrentThread(), wiele innych funkcji nadal daje mi segfault. Stworzyłem małą aplikację C do testowania biblioteki kernel32.dll.so bez pythona, ale mam zasadniczo takie same wyniki.
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;
}
Próbowałem użyć różnych konwencji wywoływania dla funkcji uśpienia(), ale nie miałem z tym szczęścia. Kiedy porównując deklaracje funkcji \ wdrożenie w źródłach wina są zasadniczo takie same
Deklaracje
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
Jednak niektóre z nich działa, a niektóre nie. Jak mogę zrozumieć, te źródła są przeznaczone dla pliku kernel32.dll, a plik kernel32.dll.so jest rodzajem proxy, które ma zapewniać dostęp do kernel32.dll dla kodu linuxowego. Prawdopodobnie muszę znaleźć dokładne źródła pliku kernel32.dll.so i zapoznać się z deklaracjami.
Czy jest jakieś narzędzie, za pomocą którego można zajrzeć do pliku .so i dowiedzieć się, jakie funkcje i jakie konwencje są używane?
Nie jestem zaznajomiony z Wine, ale uważam, że ten problem ma coś wspólnego z konwencjami wywołującymi, http://en.wikipedia.org/wiki/X86_calling_conventions, dla tych funkcji. Większość 'kernel32.dll' używa' stdcall'.Możesz spróbować wywołać niektóre funkcje z 'msvcrt.dll' lub' ws2_32.dll', większość jego funkcji używa 'cdecl', nie dostaniesz segfault. Zajrzyj tutaj, http://codepad.org/DzX33DYz. –
@Sp. Dzięki, znalazłem kilka funkcji, które mogę wywołać z kernel32.dll.to moje własne. Jednak nie mogę znaleźć żadnej różnicy między nimi a funkcjami, których potrzebuję w moim kodzie. Czy mógłbyś zaproponować mi jakieś narzędzie, aby znaleźć konwencje wywoływania funkcji wewnątrz pliku .so? –
Używam programu IDA pro, jest to bardzo przydatne w tej pracy. –