Search Unity

Reading data with pointer operation

Discussion in 'Entity Component System' started by Spy-Shifty, Nov 16, 2018.

  1. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    I try to read a component field by pointer.

    Code (CSharp):
    1.  
    2. NativeArray<T> chunkData = chunk.GetNativeArray(ArchetypeChunkComponentType);
    3. T componentData = chunkData;
    4.  
    5. //byte* dataPtr = (byte*)UnsafeUtility.PinGCObjectAndGetAddress(componentData, out var gcHandle);
    6. //UnsafeUtility.CopyStructureToPtr(ref componentData, dataPtr);
    7. byte* dataPtr = (byte*)UnsafeUtility.AddressOf(ref componentData);
    8. for (int j = 0; j < MemberInfos.Length; j++) {
    9.     var memberInfo = MemberInfos[j];
    10.     var data= dataPtr + memberInfo.Offset;    // Offset was determind by UnsafeUtility.GetFieldOffset(FieldInfo)
    11.      int value = *data << 24 | *(data + 1) << 16 | *(data + 2) << 8 | *(data + 3);
    12. }
    13. //UnsafeUtility.ReleaseGCObject(gcHandle);
    14.  

    So I've a component
    Code (CSharp):
    1.  
    2. private struct TestSyncComponent : IComponentData {
    3.     public int IntegerValue;
    4.     public int IntegerValue2;
    5. }
    6.  
    7. new TestSyncComponent {
    8.     IntegerValue = 21,     // 0x00 0x00 0x00 0x15
    9.     IntegerValue2 = 99999  //0x00 0x0F 0x42 0x3F
    10. }
    But the result is weird...
    So if I read the first integer value I get:
    *data: 0x15 --- 21
    *(data+1): 0x00 --- 0
    *(data+2): 0x15 --- 21
    *(data+3): 0x00 --- 0

    and the second integer is:
    *data: 0x9f --- 159
    *(data+1): 0x00 --- 0
    *(data+2): 0x9f --- 159
    *(data+3): 0x00 --- 0


    Is there something wrong with my code?
    Is this the correct way to get the pointer for my componet from the chunk....
     
    Last edited: Nov 17, 2018
  2. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    What if you put [StructLayout(LayoutKind.Sequential)] on the struct definition?
     
  3. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Well that just defines that two members should be layed out sequental in memory. And structs are layed out sequentually by default (classes arn't).

    Well because of the offset that doesn't matter at all. The thing is, I've the offset to the first byte of an integer. I expect that the bytes look like this:
    0x00 0x00 0x00 0x15

    But the don't and I dont know why. The address it self seams to be correct.

    By the way the ist is 0 for IntegerValue and 4 for IntegerValue2
     
  4. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    I don't get it :(
     
  5. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Ok there is a difference between reading the pointer value from the Visual studio inspector window and the value compliled by unity :)

    I'll write more later on...
     
    5argon likes this.
  6. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
    You gotta be doing something else wrong, as I'm using the exact same type of idea and very similar code, and it works perfectly.
     
    Spy-Shifty likes this.
  7. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    As I wrote before there is a bug in visual studio with pointers.

    I also had an error on building up the integer. The correct way is:
    Code (CSharp):
    1. int value1 = *data | *(data + 1) << 8 | *(data + 2) << 16 | *(data + 3) << 24;
    I've used the Inspector of Visual Studio to get the values of:
    *data, *(data+1), *(data+2)...

    The result is a different from the one if you write it in the source. I don't know why this happens exactly...


    Any way now it works!

    Thanks to @fholm for the confirmation of the correct way of doing this
     
  8. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    Is there a reason why you can't just cast it to an (int*) ?
    int value1 = *(int*)data;
     
  9. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    No, there is no reason.
    Thank you!

    Sometimes I can't see the wood for the trees...
     
  10. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    138
    Are you talking about endianness? Intel x86 uses little endian for byte ordering. I'm not sure what cases currently could implying in big endian (maybe some ARM? Power PC?), but you should check before assume that little endian will always be the case. IIRC BitConverter class can return the current ordering.

    []'s
     
  11. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    No, I speak about the Watch / QuickWatch window in Visual Studio.

    If you look for e.g. *(dataPtr + 3) in the Watch window, this will give you an complete different value as if you write it in the soure code of your programm.

    And this value has nothing todo with the real value (I've looked at the bits of all offsets). Anyway it's a bug of VS in combination with Unity...

    Everything else is working fine, therefore it's ok...
     
  12. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
    I would say for 99% of software it's basically fine to ignore endianness now a days, with x86 and basically all ARM devices being little endian (I know ARM can switch between big and little).
     
  13. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    On Unity it is 100%. We support no big endian platforms anymore.
     
  14. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
    Well that's amazing to know :)