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

Unity向C++原生插件传递字节数组:字符串出现空字节间隔问题

解决Unity传递字符串到C++出现A\0B\0C\0的问题

这个问题本质是编码不匹配导致的:Unity中的char是16位的UTF-16编码,而C里的char是8位的ASCII/UTF-8编码。当你直接把Unity的char[]传给C时,每个UTF-16字符的高字节会被填充为\0,就出现了字符间夹空字节的情况。下面给你三种常用的解决思路:

方法一:Unity侧转UTF-8字节数组传递

这是跨平台最稳妥的方案,UTF-8在C++里可以直接用char*处理,兼容性拉满。

Unity 代码:

using System.Text;
using System.Runtime.InteropServices;

public class NativeBridge : MonoBehaviour
{
    [DllImport("myDLL")]
    public static extern bool myFunc(
        byte[] strA, int lengthA,
        byte[] strB, int lengthB,
        byte[] strC, int lengthC,
        byte[] strD, int lengthD,
        byte[] strE, int lengthE
    );

    public void CallMyFunc()
    {
        string inputA = "ABC";
        // 把字符串转成UTF-8字节数组
        byte[] byteStrA = Encoding.UTF8.GetBytes(inputA);
        byte[] byteStrB = Encoding.UTF8.GetBytes("DEF");
        // 其他字符串同理处理

        // 调用C++函数,传递字节数组和对应长度
        bool result = myFunc(
            byteStrA, byteStrA.Length,
            byteStrB, byteStrB.Length,
            new byte[0], 0,
            new byte[0], 0,
            new byte[0], 0
        );
    }
}

C++ 代码:

#include <cstring>

extern "C" __declspec(dllexport) bool myFunc(
    char* strA, int lengthA,
    char* strB, int lengthB,
    char* strC, int lengthC,
    char* strD, int lengthD,
    char* strE, int lengthE
) {
    // 现在strA就是正常的UTF-8字符串"ABC",可以直接处理
    // 用lengthA做边界检查,避免越界访问
    if (strncmp(strA, "ABC", lengthA) == 0) {
        // 你的业务逻辑
    }
    return true;
}

方法二:直接传递宽字符串(Windows平台友好)

如果你的项目只针对Windows平台,直接用宽字符匹配Unity的UTF-16编码会更简单:

Unity 代码:

using System.Runtime.InteropServices;

public class NativeBridge : MonoBehaviour
{
    [DllImport("myDLL")]
    public static extern bool myFunc(
        [MarshalAs(UnmanagedType.LPWStr)] string strA,
        [MarshalAs(UnmanagedType.LPWStr)] string strB,
        [MarshalAs(UnmanagedType.LPWStr)] string strC,
        [MarshalAs(UnmanagedType.LPWStr)] string strD,
        [MarshalAs(UnmanagedType.LPWStr)] string strE
        // 宽字符串自带null结尾,可以去掉长度参数
    );

    public void CallMyFunc()
    {
        bool result = myFunc("ABC", "DEF", "", "", "");
    }
}

C++ 代码:

#include <cwchar>

extern "C" __declspec(dllexport) bool myFunc(
    wchar_t* strA,
    wchar_t* strB,
    wchar_t* strC,
    wchar_t* strD,
    wchar_t* strE
) {
    // strA现在是L"ABC",用宽字符函数处理即可
    if (wcscmp(strA, L"ABC") == 0) {
        // 你的业务逻辑
    }
    return true;
}

方法三:用Marshal类手动转换(适合老项目兼容)

如果不想修改太多C++代码,可以用Unity的Marshal类把字符串转成ANSI编码的非托管内存:

Unity 代码:

using System;
using System.Runtime.InteropServices;

public class NativeBridge : MonoBehaviour
{
    [DllImport("myDLL")]
    public static extern bool myFunc(
        IntPtr strA, int lengthA,
        IntPtr strB, int lengthB,
        IntPtr strC, int lengthC,
        IntPtr strD, int lengthD,
        IntPtr strE, int lengthE
    );

    public void CallMyFunc()
    {
        string inputA = "ABC";
        // 把字符串转成ANSI编码的非托管内存
        IntPtr ptrA = Marshal.StringToHGlobalAnsi(inputA);
        IntPtr ptrB = Marshal.StringToHGlobalAnsi("DEF");

        try {
            bool result = myFunc(
                ptrA, inputA.Length,
                ptrB, inputA.Length,
                IntPtr.Zero, 0,
                IntPtr.Zero, 0,
                IntPtr.Zero, 0
            );
        } finally {
            // 必须手动释放非托管内存,避免泄漏
            Marshal.FreeHGlobal(ptrA);
            Marshal.FreeHGlobal(ptrB);
        }
    }
}

C++ 代码:

和你原来的函数签名完全一致即可,因为StringToHGlobalAnsi生成的就是标准8位ANSI字符串:

extern "C" __declspec(dllexport) bool myFunc(
    char* strA, int lengthA,
    char* strB, int lengthB,
    char* strC, int lengthC,
    char* strD, int lengthD,
    char* strE, int lengthE
) {
    // 正常处理strA即可,就是"ABC"
    return true;
}

注意事项

  • 无论用哪种方法,都要保证编码一致性:要么全用UTF-8,要么全用UTF-16,避免乱码。
  • 如果C++需要返回字符串给Unity,也要按对应的编码转换后再传递。
  • 用Marshal手动分配内存时,一定要在finally块里释放,防止内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:32:31