2012-11-18 33 views
14

मैं सी/सी ++ लाइब्रेरी से कुछ स्ट्रिंग प्राप्त करना चाहता हूं जिसमें पाइथन में ctypes हैं। मेरे कोड इस तरह दिखता है: lib मेंपायथन ctypes: स्मृति मुक्त करने के लिए कैसे? अमान्य सूचक त्रुटि प्राप्त करना

कोड:

const char* get(struct something *x) 
{ 
    [...] 
    // buf is a stringstream 
    return strdup(buf.str().c_str()); 
} 

void freeme(char *ptr) 
{ 
    free(ptr); 
} 

अजगर कोड:

fillprototype(lib.get, c_char_p, POINTER(some_model)]) 
fillprototype(lib.freeme, None, [c_char_p]) 

// what i want to do here: get a string into python so that i can work 
// with it and release the memory in the lib. 
c_str = lib.get(some_model) 
y = ''.join(c_str) 
lib.freeme(c_str) 

तो मैं प्रिंट() c_str, सब कुछ नहीं है। अंतिम पायथन लाइन में समस्या (या प्रतीत होती है) है। मैं स्मृति मुक्त नहीं कर सकता - पुस्तकालय को गलत सूचक मिल रहा है। मैं यहाँ क्या गलत कर रहा हूँ? (और कृपया बूस्ट :: पायथन या तो सुझाव न दें)।

*** glibc detected *** python2: munmap_chunk(): invalid pointer: 0x00000000026443fc *** 
+2

क्यों 'get' एक' स्थिरांक चार * 'लेकिन' freeme' उम्मीद 'चार *' वापसी करता है? क्या आप अपने कॉलर्स को दूर करने की उम्मीद कर रहे हैं? –

+0

अच्छा बिंदु .. दुर्भाग्य से समस्या को हल नहीं किया। –

+0

क्या यह 32-बिट या 64-बिट कोड है? और क्या आप जानते हैं कि कोड की किस पंक्ति में त्रुटि आई है? यह अनिवार्य रूप से 'मुक्त (पीआरटी) 'नहीं है। –

उत्तर

18

दाऊद Schwartz के रूप में, ने कहा अगर आप c_char_p को restype निर्धारित करते हैं, ctypes एक नियमित रूप से अजगर स्ट्रिंग वस्तु देता है।

string.c:

#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 

char *get(void) 
{ 
    char *buf = "Hello World"; 
    char *new_buf = strdup(buf); 
    printf("allocated address: %p\n", new_buf); 
    return new_buf; 
} 

void freeme(char *ptr) 
{ 
    printf("freeing address: %p\n", ptr); 
    free(ptr); 
} 

अजगर उपयोग:

from ctypes import * 

lib = cdll.LoadLibrary('./string.so') 
lib.freeme.argtypes = c_void_p, 
lib.freeme.restype = None 
lib.get.argtypes = [] 
lib.get.restype = c_void_p 

>>> ptr = lib.get() 
allocated address: 0x9facad8 
>>> hex(ptr) 
'0x9facad8' 
>>> cast(ptr, c_char_p).value 
'Hello World' 
>>> lib.freeme(ptr) 
freeing address: 0x9facad8 

तुम भी एक का उपयोग कर सकते इस के आसपास पाने के लिए एक आसान तरीका एक void * का उपयोग करें और परिणाम कास्ट करने के लिए है c_char_p का उप-वर्ग। यह पता चला है कि ctypes एक साधारण प्रकार के उप-वर्ग के लिए getfunc पर कॉल नहीं करता है।

class c_char_p_sub(c_char_p): 
    pass 

lib.get.restype = c_char_p_sub 

value विशेषता स्ट्रिंग देता है। आप अधिक सामान्य c_void_p के रूप में freeme के लिए पैरामीटर छोड़ सकते हैं। यह किसी भी सूचक प्रकार या पूर्णांक पते स्वीकार करता है।

+1

यह पूरी तरह से काम किया, बहुत बहुत धन्यवाद! –

+0

ठीक है। धन्यवाद। –