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

C++/UnrealEngine Guid Base64编码与C#、JS不一致的适配咨询

问题:Unreal C++ Guid转Base64与C#/JS结果不一致的解决方案

我有一个基于C++/Unreal Engine的Windows客户端,需要和已有的C#服务器、JavaScript服务器通信。当前遇到的问题是:C中对Guid进行Base64编码的结果与C#、JS的输出不一致,排查后确认差异源于Guid转字节数组的顺序差异。由于C#和JS服务器存在其他依赖无法修改,需调整C/Unreal的代码逻辑,使编码结果与C#、JS对齐。

示例对比

// Guid字面量字符串
"3F73B3E6-7351-416F-ACA3-AE639A3F587F"

// C# & JS编码结果
"5rNzP1Fzb0Gso65jmj9Yfw"

// C++编码结果
"P3Oz5nNRQW+sowAArmOaPw"

不同在线转换器也输出两种结果,说明Guid转Base64没有统一标准:

// 与C#/JS结果一致的工具
// rcfed.com/Utilities/Base64GUID、toolslick.com/conversion/data/guid
"5rNzP1Fzb0Gso65jmj9Yfw"

// 与C++结果一致的工具
// fileformat.info/tool/guid-base64.htm
"P3Oz5nNRQW+sowAArmOaPw"

各语言现有转换代码

C#代码

Guid myGuid = new Guid("3F73B3E6-7351-416F-ACA3-AE639A3F587F");

// 对/和+进行URL编码并截断末尾的"=="填充
string strBase64Guid = Convert.ToBase64String(myGuid.ToByteArray()).Substring(0, 22).Replace("/", "_").Replace("+", "-");

JavaScript代码

var strGuid = GuidToBase64("3F73B3E6-7351-416F-ACA3-AE639A3F587F");

function GuidToBase64(guid){
    // Guid转ByteArray
    var buffer = [];
    guid.split('-').map((number, index) => {
        var bytesInChar = index < 3 ? number.match(/.{1,2}/g).reverse() : number.match(/.{1,2}/g);
        bytesInChar.map((byte) => { buffer.push(parseInt(byte, 16)); })
    });
    
    var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)));
    // 对/和+进行URL编码并截断末尾的"=="填充
    return base64String.slice(0, 22).replace("/", "_").replace("+", "-");
}

Unreal C++现有代码

FGuid& myGuid = FGuid("3F73B3E6-7351-416F-ACA3-AE639A3F587F");
FString& strGuid = myGuid.ToString(EGuidFormats::Short);


// 版权归Epic Games, Inc.所有(完整源码可在GitHub获取)

// [截断内容:函数重载及Guid格式处理]

uint32 Bytes[4] = { NETWORK_ORDER32(A), NETWORK_ORDER32(B), NETWORK_ORDER32(C), NETWORK_ORDER32(D) };
TCHAR Buffer[25];
int32 Len = FBase64::Encode(reinterpret_cast<const uint8*>(Bytes), sizeof(Bytes), Buffer);
TArrayView<TCHAR> Result(Buffer, Len);
    
// [截断内容:处理'+'和'/'并去除'=='填充]

解决方案:调整Unreal C++的Guid转字节数组顺序

问题根源

C#和JS的Guid转字节数组时,对前三个十六进制组(对应Guid的Data1、Data2、Data3部分)采用小端字节序反转,第四个组保持原顺序;而当前Unreal代码用NETWORK_ORDER32(大端)处理所有四个32位整数,导致字节顺序完全不符。

修改后的Unreal C++代码示例

FGuid myGuid("3F73B3E6-7351-416F-ACA3-AE639A3F587F");
uint8 ByteArray[16];

// 处理Data1(对应Guid第一组,小端字节序)
uint32 Data1 = myGuid.A;
ByteArray[0] = (Data1 >> 0) & 0xFF;
ByteArray[1] = (Data1 >> 8) & 0xFF;
ByteArray[2] = (Data1 >> 16) & 0xFF;
ByteArray[3] = (Data1 >> 24) & 0xFF;

// 处理Data2(对应Guid第二组,小端字节序)
uint32 Data2 = myGuid.B;
ByteArray[4] = (Data2 >> 0) & 0xFF;
ByteArray[5] = (Data2 >> 8) & 0xFF;

// 处理Data3(对应Guid第三组,小端字节序)
uint32 Data3 = myGuid.C;
ByteArray[6] = (Data3 >> 0) & 0xFF;
ByteArray[7] = (Data3 >> 8) & 0xFF;

// 处理Data4(对应Guid第四组,保持原字节顺序)
uint64 Data4 = myGuid.D;
ByteArray[8] = (Data4 >> 56) & 0xFF;
ByteArray[9] = (Data4 >> 48) & 0xFF;
ByteArray[10] = (Data4 >> 40) & 0xFF;
ByteArray[11] = (Data4 >> 32) & 0xFF;
ByteArray[12] = (Data4 >> 24) & 0xFF;
ByteArray[13] = (Data4 >> 16) & 0xFF;
ByteArray[14] = (Data4 >> 8) & 0xFF;
ByteArray[15] = (Data4 >> 0) & 0xFF;

// Base64编码
TCHAR Buffer[25];
int32 Len = FBase64::Encode(ByteArray, sizeof(ByteArray), Buffer);
FString Base64Result(Buffer, Len);

// 处理URL安全编码并截断末尾==
Base64Result = Base64Result.Left(22).Replace(TEXT("/"), TEXT("_")).Replace(TEXT("+"), TEXT("-"));

// 最终结果与C#/JS一致:"5rNzP1Fzb0Gso65jmj9Yfw"

代码说明

  1. Data1/Data2/Data3处理:按小端字节序拆分对应整数,即先取低字节再取高字节,对齐C# Guid.ToByteArray()的逻辑。
  2. Data4处理:直接按从高到低的字节顺序拆分,保持Guid原始十六进制的顺序。
  3. 后续Base64编码、URL替换和截断逻辑与原代码保持一致即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:57:14