2012-12-17 12 views
7

सीटीपीएस के बारे में ज्यादा जानकारी नहीं है, हाल ही में इसके साथ काम करना शुरू कर दिया है।ctypes में सूचक वापस कैसे पास करें?

मेरे पास सी-जैसे डीएल में एक साधारण कार्य है जो गतिशील रूप से जेनरेट की गई स्ट्रिंग के लिए एक सूचक देता है।
यह ठीक काम कर रहा है, लेकिन, क्योंकि मैंने मैन्युअल रूप से स्ट्रिंग के लिए स्मृति आवंटित की है, मुझे इसे उपयोग के बाद मुक्त करना चाहिए।

मैं कुछ इस तरह है:

extern "C" char* DLL_EXPORT func(const char* str1, const char* str2) 
{ 
    return getSomeString(str1, str2); 
} 

// Goal is to call this function correctly from Python.  
extern "C" void DLL_EXPORT freeMem(void *mem) 
    { 
     if(mem!=NULL) 
      delete mem; 
    } 

लेकिन मैं किसी भी विचार की जरूरत नहीं है, मैं कैसे पारित सूचक वापस हटाने के लिए अजगर में प्राप्त कर सकते हैं?

+0

http://stackoverflow.com/questions/7398575/deallocating-memory-for-objects-returned-to-python-through-ctypes देखें:

यहाँ एक उदाहरण (अजगर 3) है। –

उत्तर

7

आप सही रास्ते पर हैं।

// TestDLL.cpp 
#include <string.h> // strcpy 

extern "C" __declspec(dllexport) char* stringdup(const char* str) { 
    char* p = new char[strlen(str)+1]; 
    strcpy(p,str); 
    return p; 
} 

// if you have no good reason to use void*, use the type 
// you've allocated. while it usually works for built-in 
// types, it wouldn't work for classes (it wouldn't call 
// the destructor) 
extern "C" __declspec(dllexport) void stringfree(char* ptr) { 
    // you don't need to check for 0 before you delete it, 
    // but if you allocate with new[], free with delete[] ! 
    delete [] ptr; 
} 

और अजगर में:

# Test.py 
import ctypes 

lib = ctypes.cdll.TestDLL 

# this creates a c-style char pointer, initialized with a string whose 
# memory is managed by PYTHON! do not attempt to free it through the DLL! 
cstr = ctypes.c_char_p("hello ctypes") 

# call the dll function that returns a char pointer 
# whose memory is managed by the DLL. 
p = lib.stringdup(cstr) 

# p is just an integer containing the memory address of the 
# char array. therefore, this just prints the address: 
print p 

# this prints the actual string 
print ctypes.c_char_p(p).value 

# free the memory through the DLL 
lib.stringfree(p) 
+2

'stringdup.restype' को पॉइंटर प्रकार पर सेट करने की आवश्यकता है, जैसे 'POINTER (c_char)' क्योंकि डिफ़ॉल्ट परिणाम प्रकार 32-बिट' int' है। पाइथन स्ट्रिंग प्राप्त करने के लिए, आप 'cast (p, c_char_p) .value' या 'c_char_p.from_buffer (p) .value' का उपयोग कर सकते हैं। – eryksun

8

आम तौर पर प्रत्येक कार्य आप ctypes में उपयोग करती हैं इसलिए अजगर सही संख्या और तर्क के प्रकार के लिए जाँच कर सकते हैं और अजगर वस्तु तर्क कन्वर्ट अपने तर्कों और वापसी प्रकार घोषित करना चाहिए था सही सी डेटा ऑब्जेक्ट्स के लिए। दुर्भाग्य से इस मामले में, func के लिए सामान्य वापसी मूल्य c_char_p होगा, लेकिन ctypes सहायक होने की कोशिश करता है और c_char_p एक पाइथन स्ट्रिंग पर वापसी मान को परिवर्तित करता है, कच्चे सी सूचक मूल्य तक पहुंच खो देता है। इसके बजाय, आप वापसी प्रकार को c_void_p के रूप में घोषित कर सकते हैं और स्ट्रिंग मान को पुनर्प्राप्त करने के लिए cast का उपयोग कर सकते हैं, जो वापसी मान को c_char_p ऑब्जेक्ट छोड़ देता है।

import ctypes 

func = ctypes.cdll.TestDLL.func 
func.argtypes = [ctypes.c_char_p,ctypes.c_char_p] 
func.restype = ctypes.c_void_p 

freeMem = ctypes.cdll.TestDLL.freeMem 
freeMem.argtypes = [ctypes.c_void_p] 
freeMem.restype = None 

s = func(b'abcdef',b'ghijkl') 
s = ctypes.cast(s,ctypes.c_char_p) 
print(s.value) 
freeMem(s) 
संबंधित मुद्दे