You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中C#传递含字符串结构体到非托管代码时StructLayout失效问题

问题根源

Unity使用的Mono运行时与.NET 5的CoreCLR在P/Invoke结构体封送的处理逻辑上存在差异。你在C#结构体中直接用string[]对应C++的char* array[218],这种写法在CoreCLR中可以自动处理,但Mono不支持将结构体中的字符串数组直接封送,必须手动通过IntPtr中转处理。

解决方案

1. 修改C#结构体定义

将string[]替换为IntPtr[],因为IntPtr可以直接对应C++中的char*指针:

using System;
using System.Runtime.InteropServices;
using UnityEngine;
using System.Collections.Generic;

public class DLLTEST : MonoBehaviour
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct MOVES_IMPORT
    {
        public int size; // 改为public,确保Marshal能访问成员
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 218)]
        public IntPtr[] Array;
    };

    [DllImport("LittleChessEngine.dll")]
    static extern int EXP_LEGAL_MOVES(ref MOVES_IMPORT mvs);

    // 如果C++中用malloc分配了字符串内存,需要添加释放函数的导入
    // [DllImport("LittleChessEngine.dll")]
    // static extern void EXP_FREE_MOVE_STRING(IntPtr strPtr);

    void Start()
    {
        var mvs = new MOVES_IMPORT();
        // 初始化IntPtr数组,避免Mono报错
        mvs.Array = new IntPtr[218];
        var size = EXP_LEGAL_MOVES(ref mvs);

        // 手动将IntPtr转换为C#字符串
        List<string> legalMoves = new List<string>();
        for (int i = 0; i < mvs.size; i++)
        {
            if (mvs.Array[i] != IntPtr.Zero)
            {
                string move = Marshal.PtrToStringAnsi(mvs.Array[i]);
                legalMoves.Add(move);
                // 释放C++分配的内存(如果需要)
                // EXP_FREE_MOVE_STRING(mvs.Array[i]);
            }
        }

        // 这里可以使用legalMoves列表做后续处理
        foreach(var move in legalMoves)
        {
            Debug.Log("合法走法:" + move);
        }
    }
}

2. 注意内存泄漏问题

如果你的C++引擎中是通过malloc/new分配的char*内存,必须在DLL中提供对应的释放函数,并在C#中调用释放每个指针,否则会造成内存泄漏。

C++侧释放函数示例:

extern "C" __declspec(dllexport) void EXP_FREE_MOVE_STRING(char* str)
{
    if(str != nullptr)
    {
        free(str); // 如果用new分配则用delete[]
    }
}
为什么.NET 5能正常运行?

.NET 5使用的CoreCLR对结构体中字符串数组的封送做了特殊处理,会自动将C++的char*指针数组转换为C#的string[]。但Unity的Mono运行时没有实现这个自动转换逻辑,必须手动处理指针到字符串的转换。

内容的提问来源于stack exchange,提问作者bogdane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:32:35