كيفية تنظيم المخزن المؤقت غير المُدار للبنيات المعبأة في C#

StackOverflow https://stackoverflow.com/questions/506231

سؤال

أقوم (بنجاح) باستدعاء وظيفة Windows FilterSendMessage في c# باستخدام توقيع الدبوس التالي:

[DllImport("fltlib.dll")]
    public static extern IntPtr FilterSendMessage(
        IntPtr hPort,
        IntPtr inBuffer,
        UInt32 inBufferSize,
        IntPtr outBuffer,
        UInt32 outBufferSize,
        out UInt32 bytesReturned);

ال outBuffer يتم ملء المعلمة بعدد عشوائي من البنيات (معبأة واحدة تلو الأخرى)، المحددة في لغة C على النحو التالي:

typedef struct _BAH_RECORD {

    int evt
    int len;
    WCHAR name[1];

} BAH_RECORD, *PBAH_RECORD;

ال اسم يتم تعيين طول متغير للحقل، وسلسلة Unicode منتهية بقيمة خالية.ال لين يصف الحقل الحجم الإجمالي للبنية بالبايت (بما في ذلك سلسلة الاسم).أنا واثق من أنه لا يوجد خطأ في كيفية التعامل مع الهياكل في الجانب غير المُدار من الأشياء.

تنشأ مشكلتي عندما أحاول تنظيم outBuffer إلى مثيل من بنية BAH_RECORD، المحددة في c# على النحو التالي:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct BAH_RECORD
{
    public UInt32 evt;
    public UInt32 len;
    public string name;
}

IntPtr outBuffer = Marshal.AllocHGlobal(OUT_BUFFER_SIZE);

hResult = Win32.FilterSendMessage(hPortHandle, inBuffer, IN_BUFFER_SIZE, outBuffer, OUT_BUFFER_SIZE, out bytesReturned);

BAH_RECORD bah = (BAH_RECORD)Marshal.PtrToStructure(outBuffer, typeof(BAH_RECORD));

<snip>

إذا حاولت طباعة/عرض/عرض bah.name، أحصل على القمامة...

للتأكد من أن outBuffer يحتوي فعليًا على بيانات صالحة، قمت بإجراء بعض الاختراقات الأولية للمؤشر في لغة c# للتنقل عبرها، واستدعاء Marshal.ReadInt32 مرتين (لتغطية أول حقلين للبنية)، ثم Marshal.ReadByte عدة مرات لملء بايت [] والتي أستخدمها بعد ذلك كوسيطة لـ Encoding.Unicode.GetString()... السلسلة تظهر بشكل جيد، لذلك فهي موجودة بالتأكيد، لا يبدو أنني أجعل المنظم يتعامل معها بشكل صحيح (حتى لو كان الأمر كذلك) يستطيع؟)

أي مساعدة موضع تقدير

ستيف

هل كانت مفيدة؟

المحلول

تكمن المشكلة في أن سلسلة "الاسم" في بنية C# BAH_RECORD يتم تنظيمها كمؤشر إلى سلسلة (WCHAR*) ولكنها على الجانب C عبارة عن مخزن مؤقت WCHAR مضمن.لذلك عندما تقوم بتنظيم البنية الخاصة بك، يقرأ وقت التشغيل البايتات الأربعة الأولى من المخزن المؤقت كمؤشر ثم يحاول قراءة السلسلة التي يشير إليها.

لسوء الحظ، لا توجد طريقة لوقت التشغيل لتنظيم المخازن المؤقتة ذات الحجم المتغير تلقائيًا داخل البنيات، لذا ستحتاج إلى استخدام التنظيم اليدوي (أو كما تقول "اختراق المؤشر").ولكن عندما تقدم المؤشر للإشارة إلى المخزن المؤقت، فلن تحتاج إلى قراءة البايتات بشكل فردي ثم تحويلها إلى سلسلة - فقط اتصل بـ Marshal.PtrToStringUni.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top