4

プリミティブ構造を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;
    }
}

なぜ私は44ではなく12を受け取っているのreturnedStruct.valueTypeですか?

4

1 に答える 1

4

ここには2つのエラーがあります。

意味的には、設定していますcustom.valueType = 44が、構造が戻ったときにチェックcustom.referenceType->valueTypeしています。これは44ではなく0である必要があります。

2番目のエラーは、マーシャリングを解除するMarshal.FreeCoTaskMem()に、このポインター(custom.referenceType)を呼び出していることです。これは、未割り当てのメモリを構造体にアンマーシャリングしていることを意味します。この時点では、これは未定義の動作であり、12の回答は、アクセス違反を受け取った場合と同じように有効な結果です。Custom


最初の問題を修正するには、マーシャリングを解除returnedStruct.valueType せずにチェックするか、にマーシャリングする前に44にreturnedStruct.referenceType設定する必要があります。childStruct.valueTypeptrToStructure

2番目の問題を修正するには、とを呼び出す順序を逆にする必要がありMarshal.PtrToStructure()ますMarshal.FreeCoTaskMem()

于 2013-01-04T16:09:03.597 に答える