سؤال

واني اسعى الى الحصول على C # تطبيق WPF للتواصل مع تطبيق آخر مكتوب في C باستخدام WM_COPYDATA. التطبيق C تحاول إرسال البنية كما يلي:

typedef struct
{
    int x;
    int y;
    char str[40];
    double d;
    char c;
} DATASTRUCT;

في بلدي C # التطبيق لقد تعريف البنية كما يلي:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct DATASTRUCT
{
    public int x;
    public int y;
    [MarshalAs(UnmanagedType.LPStr, SizeConst=40)]
    public string s;
    public double d;
    public char c;
};

ورمز لتلقي رسالة WM_COPYDATA هو كما يلي:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
    hwndSource.AddHook(new HwndSourceHook(WndProc));
}

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if (msg == 0x4A)
    {
        DATASTRUCT data = (DATASTRUCT)Marshal.PtrToStructure(lParam, typeof(DATASTRUCT));
        this.updateText(data);
        handled = true;
    }

    return (IntPtr)0;
}

وأنا أتلقى رسائل من تطبيق C، ولكن جميع البيانات في البنية هو رطانة. وقبل ذلك كنت قادرا على استخراج يدويا مجموعة من وحدات البايت من مؤشر lParam ثم استخدام System.BitConverter وSystem.Text.Encoding.ACII لتفسير صفيف بايت، والتي عملت بشكل جيد جدا. ولكن الآن أنا أحاول أن تفعل ذلك بطريقة أنظف وانها مجرد لا يعمل.

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

المحلول

وبعد فترة طويلة يبحثون عن الجواب على هذا السؤال، وأنا أدرك أن كنت في عداد المفقودين خطوة مهمة جدا. أشعر احمق، ولكن وهنا يكمن الجواب على سؤالي الخاص.

ووC # البنية ينبغي أن تبدو هذه:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public unsafe struct DataStruct
{
    public int x;
    public int y;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=40)]
    public string s;
    public double d;
    public char c;
};

ويجب أن تكون محددة البنية أخرى لاستقبال المعلومات WM_COPYDATA. يبدو مثل هذا:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public unsafe struct CopyDataStruct
{
    public IntPtr dwData;
    public int cbData;
    public IntPtr lpData;
}

ويجب تغيير أسلوب WndProc لتبدو مثل هذا:

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if (msg == 0x4A)
    {
        CopyDataStruct cps = (CopyDataStruct)Marshal.PtrToStructure(lParam, typeof(CopyDataStruct));
        DataStruct data = (DataStruct)Marshal.PtrToStructure(cps.lpData, typeof(DataStruct));
        updateText(data);
        handled = true;
    }

    return (IntPtr)0;
}

وكنت تستخدم CopyDataStruct في بلدي حل العاملة السابق، وأنا فقط نسيت أن استخدامه في الإصدار الأحدث.

نصائح أخرى

وجزء من المشكلة هو أن العضو شارع لابد أن يكون ByValTStr ليس LPSTR حيث أنها مجموعة سلسلة inlined. جرب التعريف التالي

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct DATASTRUCT
{
    public int x;
    public int y;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=40)]
    public string s;
    public double d;
    public char c;
};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top