编组后字段中的值错误

本文关键字:错误 字段 | 更新日期: 2023-09-27 17:50:45

我正在尝试将原始结构从c++编组到c#,并有以下代码:

using System;
using System.Runtime.InteropServices;
namespace dotNet_part
{
    class Program
    {
        static void Main(string[] args)
        {
            Custom custom = new Custom();
            Custom childStruct = new Custom();
            IntPtr ptrToStructure = Marshal.AllocCoTaskMem(Marshal.SizeOf(childStruct));
            Marshal.StructureToPtr(childStruct, ptrToStructure, true);
            custom.referenceType = ptrToStructure;
            custom.valueType = 44;
            Custom returnedStruct = structureReturn(custom);
            Marshal.FreeCoTaskMem(ptrToStructure);
            returnedStruct = (Custom)Marshal.PtrToStructure(returnedStruct.referenceType, typeof(Custom));
            Console.WriteLine(returnedStruct.valueType); // Here 'm receiving 12 instead of 44
        }
        [return:MarshalAs(UnmanagedType.I4)]
        [DllImport("CPlusPlus part.dll")]
        public static extern int foo(Custom param);
        // [return:MarshalAs(UnmanagedType.Struct)]
        [DllImport("CPlusPlus part.dll")]
        public static extern Custom structureReturn(Custom param);
    }
    [StructLayout(LayoutKind.Sequential)]
    struct Custom
    {
        [MarshalAs(UnmanagedType.I4)]
        public int valueType;
        public IntPtr referenceType;
    }
}

和c++部分:

typedef struct Custom CUSTOM;
extern "C"
{
    struct Custom
    {
       int valueType;
       Custom* referenceType;
    } Custom;
    _declspec(dllexport) int foo(CUSTOM param)
    {
      return param.referenceType->valueType;
    }
    _declspec(dllexport) CUSTOM structureReturn(CUSTOM param)
    {
      return param;
    }
}

为什么我在returnedStruct.valueType中收到的是12而不是44 ?

编组后字段中的值错误

这里有两个错误:

在语义上,您正在设置custom.valueType = 44,但在返回结构时,您正在检查custom.referenceType->valueType,它不应该是44 -它应该是0。

第二个错误是您在解组之前在该指针(custom.referenceType) 上调用Marshal.FreeCoTaskMem() !这意味着您正在将未分配内存解组到Custom结构体中。在这一点上,这是未定义的行为,并且12的答案与接收到访问冲突一样有效。

要解决第一个问题,您需要检查returnedStruct.valueType 而不将returnedStruct.referenceType解封送,或者您需要在将childStruct.valueType封送到ptrToStructure之前将其设置为44。

要解决第二个问题,需要颠倒调用Marshal.PtrToStructure()Marshal.FreeCoTaskMem()的顺序。