Segfault when calling standard .dll windows from python ctypes with wine

I am trying to call some function from Kernel32.dll in my Python script running on Linux. As Johannes Weiß pointed out How to call a dll from python on Linux? I load the kernel kernel32.dll.so library through ctypes.cdll.LoadLibrary () and it loads normally. I can see that kernel32 is loaded and even has a GetLastError () function inside. However, whenever I try to call the i function, you get 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 

At first I thought about challenging the odds, but everything seems to be in order. I am finishing testing a simple GetLastError function without any parameters, but I still get a segmentation error.

My testing system is Ubuntu 12.10, Python 2.7.3 and wine-1.4.1 (all 32 bits)

UPD

I continue testing and find several functions that I can call through ctypes without segfault. For example, I can name the functions Beep () and GetCurrentThread (), many other functions still give me segfault. I created a small C application to test the kernel32.dll.so library without python, but I have almost the same results.

 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 eg 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; } 

I tried to use various calling conventions for the Sleep () function, but also no luck. When I compare function declarations \ implementations in Wine sources, they are essentially the same

ads

  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 

However, some of them work, and some do not. Since I can understand that these are sources for the kernel32.dll file, and the kernel32.dll.so file is some kind of proxy server that should provide access to kernel32.dll for linux code. I probably need to find the exact sources of the kernel32.dll.so file and take a look at the ads.

Is there any tool I can use to look inside the .so file and find out what features and conventions are used?

+6
source share
1 answer

The easiest way to learn DLLs is to use the nm command, i.e.

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

As others have noted, the default calling convention for a DLL for Windows C is stdcall . This has nothing to do with using Python. On the Windows platform, ctypes.windll available.

However, I'm not even sure that you are trying to make this possible . Wine is a full-blown Windows emulator, and it is safe to assume that at least you should start it with wine_init before loading any other functions. The Windows API probably has a certain state (set when Windows boots up).

The easiest way to continue is probably to install the Windows Python version under Wine and run the script there.

0
source

All Articles