2009-09-24 20 views
9

मैं ctypes के साथ अजगर में सी कोड का एक टुकड़ा की नकल करना चाहते हैं, कोड कुछ की तरह है:अजगर ctypes: प्रतिलिपि बनाई जा रही संरचना की सामग्री

typedef struct { 
    int x; 
    int y; 
} point; 

void copy_point(point *a, point *b) { 
    *a = *b; 
} 

ctypes यह संभव नहीं है में करने के लिए निम्नलिखित:

from ctypes import * 

class Point(Structure): 
    _fields_ = [("x", c_int),("y", c_int)] 

def copy_point(a, b): 
    a.contents = b.contents 

p0 = pointer(Point()) 
p1 = pointer(Point()) 
copy_point(p0,p1) 

contents के रूप में अभी भी एक पाइथन ctypes संरचना वस्तु है, जिसे संदर्भ के रूप में प्रबंधित किया जाता है।

एक स्पष्ट कामकाज प्रत्येक क्षेत्र को मैन्युअल रूप से प्रतिलिपि बनाना होगा (जिसे अपरिवर्तनीय पायथन इंट के रूप में दर्शाया गया है), लेकिन यह अधिक जटिल संरचनाओं के साथ स्केल नहीं करता है। इसके अलावा, इसे उन क्षेत्रों के लिए पुनरावर्ती रूप से किया जाना चाहिए जो बुनियादी नहीं हैं, बल्कि संरचित प्रकार हैं।

मेरे अन्य विकल्प memmove का उपयोग करें और वस्तुओं कॉपी रूप में यदि वे बफ़र्स थे करने के लिए है, लेकिन जैसा कि अजगर गतिशील रूप से लिखा गया यह अलग प्रकार और आकार की वस्तुओं के साथ इसका इस्तेमाल करने के लिए बहुत आसान होती है कि बहुत त्रुटियों की संभावना लगता है (, प्रमुख स्मृति भ्रष्टाचार या विभाजन दोषों के लिए) ...

कोई सुझाव?

संपादित:

मैं भी संरचना के एक ताजा नई प्रतिलिपि इस्तेमाल कर सकते हैं, तो हो सकता है यह उपयोगी हो सकता है:

import copy 
p0 = Point() 
p1 = copy.deepcopy(p0) #or just a shallow copy for this example 

लेकिन मैं अगर वहाँ किसी तरह का हो सकता है पता नहीं है के विचित्र व्यवहार ctypes proxys को कॉपी रूप में यदि वे नियमित रूप से अजगर वस्तुओं थे ...

+1

दुर्भाग्य से 'deepcopy' विफल रहता है ctypes संरचना संकेत शामिल हैं:' ValueError: ctypes संकेत युक्त वस्तुओं pickled' नहीं किया जा सकता। – 101

उत्तर

5

आप अनुक्रम काम (बल्कि p.contents, जो सूचक मूल्य में परिवर्तन करने के लिए बताए से) का उपयोग की वस्तुओं की ओर इशारा किया-कॉपी करने के लिए कर सकते हैं प्रूफ, लेकिन यह कुछ भी नहीं है)। उपयोग की

उदाहरण के लिए, सत्यापन है कि यह तथ्य काम में करता है के साथ;):

>>> o1 = Point(1, 1) 
>>> o2 = Point(2, 2) 
>>> print (o1.x, o1.y, addressof(o1)), (o2.x, o2.y, addressof(o2)) 
(1, 1, 6474004) (2, 2, 6473524) 
>>> copy(o2, o1) 
>>> pprint (o1.x, o1.y, addressof(o1)), (o2.x, o2.y, addressof(o2)) 
(1, 1, 6474004) (1, 1, 6473524) 

>>> o1 = Point(1, 1), o2 = Point(2, 2) 
>>> print (o1.x, o1.y, addressof(o1)), (o2.x, o2.y, addressof(o2)) 
(1, 1, 6473844) (2, 2, 6473684) 
>>> p1, p2 = pointer(o1), pointer(o2) 
>>> addressof(p1.contents), addressof(p2.contents) 
(6473844, 6473684) 
>>> ptr_copy(p1, p2) 
>>> print (o1.x, o1.y, addressof(o1)), (o2.x, o2.y, addressof(o2)) 
(2, 2, 6473844) (2, 2, 6473684) 
>>> addressof(p1.contents), addressof(p2.contents) 
(6473844, 6473684) 
+0

समझा जाता है, लेकिन यह सिर्फ बदलता है पॉइंट: - प्रिंट करने के बाद असाइन करने के बाद (src) और पता (dst.contents) प्रिंट करें। – fortran

+0

उन फ़ंक्शंस को पॉइंटर्स पास नहीं किया जाना चाहिए, उन्हें 'ctypes' संरचना ऑब्जेक्ट्स माना जाता है। यदि आप अपने सी 'copy_point' के अनुरूप एक फ़ंक्शन चाहते हैं,' dst [0] = src [0] ' – Miles

+0

हम्मम्म ... मैं नहीं देख सकता कि व्यवहार 'dst = पॉइंटर (ए) करने से क्यों बदल गया; dst [0] = src; 'to 'सूचक (ए) [0] = src': - | – fortran

0

मैं अब भी तरह एक विधि को परिभाषित करने के बारे में सोच रहा हूँ:

def safe_copy(dst, src): 
    if type(src) != type(dst) or not isinstance(src, Structure): 
    raise Exception("wrong types") 
    memmove(addressof(dst), addressof(src), sizeof(src)) 

लेकिन वहाँ अभी भी अच्छे विकल्प हो सकती है ...

नियम के रूप में
+0

कुछ वर्तनी त्रुटियां लेकिन सुरक्षा जांच प्रकार की अनुशंसा की जाती है। – whatnick

0

सूचक संचालन सुरक्षित बहुत स्मृति नहीं हैं। मैं प्रत्येक स्ट्रक्चर डेटा प्रकार के लिए रैपर कक्षाएं तैयार करूंगा जिसमें आप रुचि रखते हैं और उन्हें पॉइंटर कॉपी ऑपरेशंस को संभालने दें। आप यहां बहुत कुछ कर रहे हैं। लैम्ब्डा और नक्शा फ़ंक्शंस हैं जिन्हें आप सिंटेक्टिक चीनी के रूप में पुनरावर्ती रूप से उपयोग कर सकते हैं।

def copy(dst, src): 
    """Copies the contents of src to dst""" 
    pointer(dst)[0] = src 

# alternately 
def new_copy(src): 
    """Returns a new ctypes object which is a bitwise copy of an existing one""" 
    dst = type(src)() 
    pointer(dst)[0] = src 
    return dst 

# or if using pointers 
def ptr_copy(dst_ptr, src_ptr): 
    dst_ptr[0] = src_ptr[0] 

ctypes प्रकार आप के लिए जाँच (जो मूर्ख नहीं है क्या करेंगे:

+2

क्या एक शून्य जवाब है :-( – fortran

+0

जोर से सोचने की कीमत .. मेटाक्लास हैं जो एक अच्छा मैपिंग तंत्र का उपयोग किया जा सकता है। Http: //code.activestate.com/recipes/576666/ – whatnick

6

memmove यहाँ सही संचालन है। अपने CopyPoint फ़ंक्शन के argtypes को सेट करके, आप आसानी से टाइप-सुरक्षा लागू कर सकते हैं।

from ctypes import * 

class Point(Structure): 
    _fields_ = [("x", c_int), ("y", c_int)] 
    def __str__(self): 
     return "<Point: x=%d, y=%d, addr=%ld>" % (self.x, self.y, addressof(self)) 

def CopyPoint(a, b): 
    memmove(a, b, sizeof(Point)) 
CopyPoint.argtypes = [POINTER(Point), POINTER(Point)] 

pt0 = Point(x=0, y=10) 
pt1 = Point(x=5, y=7) 

print pt0, pt1 

CopyPoint(byref(pt0), byref(pt1)) 
print pt0, pt1  

try: 
    CopyPoint(byref(pt0), Point(x=2, y=3)) 
except ArgumentError as e: 
    print "Could not copy!", e 

आउटपुट:

$ python ct.py 
<Point: x=0, y=10, addr=3083711192> <Point: x=5, y=7, addr=3083711120> 
<Point: x=5, y=7, addr=3083711192> <Point: x=5, y=7, addr=3083711120> 
Could not copy! argument 2: <type 'exceptions.TypeError'>: wrong type 

ध्यान दें कि आप आसानी से एक कारखाना बना सकता है एक विशिष्ट प्रकार के आधार पर, यदि आप सामान्यीकरण करने की जरूरत रन-टाइम में समारोह के इस प्रकार उत्पन्न करने के लिए:

def CopierFactory(typ): 
    def f(a,b): 
     memmove(a,b, sizeof(typ)) 
    f.argtypes = [POINTER(typ), POINTER(typ)] 

    return f 

copy_point = CopierFactory(Point) 

a = Point(x=1, y=2) 
b = Point(x=-1, y=-1) 
print a, b 
copy_point(byref(a), byref(b)) 
print a, b 

उत्पादन:

<Point: x=1, y=2, addr=3085088024> <Point: x=-1, y=-1, addr=3085087952> 
<Point: x=-1, y=-1, addr=3085088024> <Point: x=-1, y=-1, addr=3085087952> 
0

पायथन 3x में, आपका कोड सही ढंग से चलाया जा सकता है। नीचे दिखाया गया है:

>>> from ctypes import * 
>>> class Point(Structure): 
... _fields_ = [("x", c_int),("y", c_int)] 
>>> def copy_point(a, b): 
... a.contents = b.contents 
>>> p0 = pointer(Point()) 
>>> p1 = pointer(Point(1,2)) 
>>> p0.contents.x 
0 
>>> copy_point(p0,p1) 
>>> p0.contents.x 
1 
संबंधित मुद्दे

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