c# - 编码后字段中的错误值

标签 c# c++ marshalling

我正在尝试将原始结构从 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 到 44,然后再将其编码到 ptrToStructure

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

关于c# - 编码后字段中的错误值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14160512/

相关文章:

c# - C Dll 导入在 C# 中引发 Marshall 指令异常

java - 该对象与 JSON/XML 之间的(解)编码可能会破坏到什么程度

c# - 使用 ASp.net MVC3 插入数据库后如何显示类似 "successfully Inserted"的警告消息

c# - ASP.NET Core 如何让 UserManager 在 Controller 中工作?

c# - C# 中 HTML 换行符的常量?

c# - 在应用程序 Xcode 中编写代码

c++ - Win32 中原生 C/C++ 的高级 HTTP 客户端库

c++ - Qt5 -static x64 和链接噩梦

c++ - 第一个带有 double 的 setw 是左对齐的,随后是右对齐的

java - 在 XML 文件中看不到命名空间前缀