سؤال

قد يكون هذا سؤال سخيف لكن لم أجد إجابة جيدة في المستندات أو في أي مكان.

إذا كنت تستخدم البنية لتحديد ثنائي الهيكل ، فإن البنية 2 متناظرة أساليب التسلسل وإلغاء التسلسل (حزمة وفك) ولكن يبدو ctypes لا يملك وسيلة واضحة للقيام بذلك.هنا هو الحل الذي يشعر الخطأ:

from ctypes import *

class Example(Structure):
    _fields_ = [
        ("index", c_int),
        ("counter", c_int),
        ]

def Pack(ctype_instance):
    buf = string_at(byref(ctype_instance), sizeof(ctype_instance))
    return buf

def Unpack(ctype, buf):
    cstring = create_string_buffer(buf)
    ctype_instance = cast(pointer(cstring), POINTER(ctype)).contents
    return ctype_instance

if __name__ == "__main__":
    e = Example(12, 13)
    buf = Pack(e)
    e2 = Unpack(Example, buf)
    assert(e.index == e2.index)
    assert(e.counter == e2.counter)
    # note: for some reason e == e2 is False...
هل كانت مفيدة؟

المحلول

على PythonInfo ويكي وقد حل هذا.

التعليمات:كيف يمكنني نسخ بايت إلى الثعبان من ctypes.هيكل ؟

def send(self):
    return buffer(self)[:]

التعليمات:كيف يمكنني نسخ بايت إلى ctypes.هيكل من الثعبان ؟

def receiveSome(self, bytes):
    fit = min(len(bytes), ctypes.sizeof(self))
    ctypes.memmove(ctypes.addressof(self), bytes, fit)

بهم send هو (أكثر أو أقل) أي ما يعادل pack, ، receiveSome هو نوع من pack_into.إذا كان لديك "آمنة" حالة حيث كنت الفتح في البنية من نفس النوع الأصلي ، يمكنك سطر واحد مثل memmove(addressof(y), buffer(x)[:], sizeof(y)) نسخ x في y.بالطبع سيكون لديك ربما متغير ما الحجة الثانية بدلا من حرفية التعبئة x.

نصائح أخرى

إلقاء نظرة على هذا الرابط على الثنائية i/o في بايثون:

http://www.dabeaz.com/blog/2009/08/python-binary-io-handling.html

وبناء على هذا يمكن ببساطة كتابة التالية قراءة من المخزن المؤقت (وليس فقط الملفات):

g = open("foo","rb")
q = Example()
g.readinto(q)

أن تكتب هو ببساطة:

g.write(q)

نفس الشيء بالنسبة باستخدام مآخذ:

s.send(q)

و

s.recv_info(q)

فعلت بعض التجارب مع حزمة/فك ctypes و هذا النهج هو أسرع ما عدا الكتابة مباشرة في ج

اختبار على Python3

e = Example(12, 13)
serialized = bytes(e)
deserialized = Example.from_buffer_copy(serialized)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top