Reputation: 294
Using the NetworkInfo2SecurityParameter
function I am trying to copy the fixed-size buffer unkRandom
from from LdnNetworkInfo
struct held in NetworkInfo
struct to the SecurityParameter
struct's buffer.
Basically I am making a method to convert these two types, and I want to copy these two arrays to another. This code features all structs relevant.
The error is happening at the Buffer.MemoryCopy()
function. The error is "You cannot use fixed size buffers contained in unfixed expressions. Try using the 'fixed' statement"
unsafe void NetworkInfo2SecurityParameter(NetworkInfo info, out SecurityParameter output)
{
output = new SecurityParameter();
output.sessionId = info.networkId.sessionId;
Buffer.MemoryCopy(output.unkRandom, info.ldn.unkRandom, 16, 16);
}
struct SecurityParameter {
public unsafe fixed byte unkRandom[16];// = new byte[16];
public SessionId sessionId;
};
struct NetworkInfo : /sf::/LargeData {
public NetworkId networkId;
public CommonNetworkInfo common;
public LdnNetworkInfo ldn;
};
struct LdnNetworkInfo {
public unsafe fixed byte unkRandom[16];// = new byte[16];
public ushort securityMode;
public byte stationAcceptPolicy;
public unsafe fixed byte _unk1[3];// = new byte[3];
public byte nodeCountMax;
public byte nodeCount;
//TODO non primitive array,,
private unsafe fixed byte _nodes[sizeof(NodeInfo)*NodeCountMax]; //Needs to be fixed array, and needs to be casted to NodeInfo span, so thats why its size is this
public unsafe fixed Span<NodeInfo> nodes => MemoryMarshal.Cast<byte, NodeInfo>(MemoryMarshal.CreateSpan(ref _nodes[0], 128));
public ushort _unk2;
public ushort advertiseDataSize;
public unsafe fixed byte advertiseData[AdvertiseDataSizeMax];// = new byte[AdvertiseDataSizeMax];
public unsafe fixed byte _unk3[148];// = new byte[148];
};
Upvotes: 1
Views: 696
Reputation: 8847
struct
is assignable, like any primitive. Undoubtedly faster than Buffer.MemoryCopy()
would be:
public unsafe struct FixedSizeBufferWrapper
{
public unsafe fixed byte unkRandom[16];
}
unsafe
{
fixed (byte* firstStruct = somewhere.securityParameter, otherStruct = somewhereElse.ldnNetworkInfo )
{
//one assignment blits all contents
*((FixedSizeBufferWrapper*)firstStruct.unkRandom) =
*((FixedSizeBufferWrapper*)otherStruct.unkRandom);
}
}
We cast buffers in each of your original structs to the wrapper pointer type and dereference each pointer SO THAT we can assign one to the other; assigning fixed
buffers directly is not possible.
We have to cast outside the fixed
statement because (at least in my version of C#) we aren't allowed to cast inside fixed(...)
and we cannot assign anything other than a primitive type (usually byte[]
) as the buffer type. The wrapper struct exists purely for this casting / assignment.
Upvotes: 1
Reputation: 294
Fixed it with this approach: I created a new variable called ret, which I did copy the data to, and then I assigned ret to output.
unsafe void NetworkInfo2SecurityParameter(NetworkInfo info, out SecurityParameter output)
{
var ret = new SecurityParameter();
output.sessionId = info.networkId.sessionId;
Buffer.MemoryCopy(ret.unkRandom, info.ldn.unkRandom, 16, 16);
output = ret;
}
Upvotes: 0