2013-01-21 16 views
6

मैं अपने अजगर स्क्रिप्ट लिनक्स पर चल में Kernel32.dll से कुछ समारोह कॉल करने के लिए कोशिश कर रहा हूँ के साथ अजगर ctypes से .dll। जैसा कि जोहान्स वीआईएस ने How to call Wine dll from python on Linux? की ओर इशारा किया है, मैं kernel32.dll.so लाइब्रेरी ctypes.cdll.LoadLibrary() लोड कर रहा हूं और यह ठीक लोड हो रहा है। मैं kernel32 लोड देख सकते हैं और यहां तक ​​कि GetLastError() समारोह के अंदर है। हालांकि जब भी मैं फ़ंक्शन को कॉल करने की कोशिश कर रहा हूं, तो मैं segfault प्राप्त कर रहा हूं।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 समारोह परीक्षण के साथ समाप्त कर रहा हूँ लेकिन मैं अभी भी विभाजन गलती वैसे भी हो रही है।

मेरे परीक्षण प्रणाली (सब कुछ 32 बिट है) उबंटू 12.10, पायथन 2.7.3 और शराब 1.4.1 है

युपीडी

मैं अपने परीक्षण के साथ आगे बढ़ना और कई कार्य है कि मैं फोन कर सकते हैं लगता है segfault के बिना ctypes के माध्यम से। उदाहरण के लिए मैं बीप() और GetCurrentThread नाम कर सकते हैं() काम करता है, कई अन्य कार्यों अभी भी मुझे segfault दे। मैंने 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; 
} 

मैं नींद के लिए() फ़ंक्शन अलग बुला परंपराओं का उपयोग करने की कोशिश कर, लेकिन यह भी नहीं नसीब हो गया था। जब मैं शराब स्रोतों में समारोह घोषणाओं \ कार्यान्वयन की तुलना वे अनिवार्य रूप से कर रहे हैं एक ही

घोषणाएं

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 फ़ाइल के अंदर एक बार देख ले और क्या काम करता है और क्या बुला सम्मेलनों उपयोग किया जाता है पता लगाने के लिए उपयोग कर सकते हैं है?

+0

मैं शराब से परिचित नहीं हूं, लेकिन मेरा मानना ​​है कि इन मुद्दों के लिए कॉलिंग सम्मेलनों, http://en.wikipedia.org/wiki/X86_calling_conventions के साथ इस मुद्दे का कुछ संबंध है। अधिकांश 'kernel32.dll'' stdcall' का उपयोग करता है।आप 'msvcrt.dll' या' ws2_32.dll' से कुछ फ़ंक्शंस कॉल करने का प्रयास कर सकते हैं, इसके अधिकांश फ़ंक्शन 'cdecl' का उपयोग करते हैं, आपको segfault नहीं मिलेगा। यहां देखें, http://codepad.org/DzX33DYz। –

+0

@ एसपी। धन्यवाद, मुझे कुछ फ़ंक्शंस मिले हैं जिन्हें मैं kernel32.dll.so से स्वयं कॉल कर सकता हूं। हालांकि मुझे उनके कोड में आवश्यक कार्यों और कार्यों के बीच कोई अंतर नहीं मिल रहा है। क्या आप कृपया मुझे फाइल के अंदर फ़ंक्शन के लिए कॉलिंग सम्मेलनों को खोजने के लिए कोई टूल सुझा सकते हैं। इसलिए फ़ाइल? –

+0

मैं आईडीए प्रो का उपयोग करता हूं, यह इस नौकरी के लिए बहुत उपयोगी है। –

उत्तर

0

एक DLL जांच करने के लिए सबसे आसान तरीका है, nm आदेश का उपयोग करने के लिए है अर्थात

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

के रूप में अन्य लोगों ने बताया है, विंडोज सी DLLs के लिए डिफ़ॉल्ट कॉलिंग सम्मेलन stdcall है। पाइथन का उपयोग करने के साथ इसका कोई लेना-देना नहीं है। विंडोज प्लेटफार्म पर, ctypes.windll उपलब्ध है।

हालांकि, मुझे यह भी सुनिश्चित नहीं है कि आप क्या करने की कोशिश कर रहे हैं, यह संभव है। शराब एक पूर्ण उड़ा हुआ विंडोज एमुलेटर है और यह अनुमान लगाने में सुरक्षित है कि कम से कम आपको इसे किसी भी अन्य कार्यों को लोड करने से पहले wine_init से शुरू करना होगा। विंडोज एपीआई में शायद कुछ राज्य है (विंडोज बूट होने पर सेट)।

जारी रखने के लिए सबसे आसान तरीका शायद शराब के तहत अजगर का एक Windows संस्करण स्थापित है और वहाँ से अपनी स्क्रिप्ट को चलाने के लिए है।

संबंधित मुद्दे