urho
urho copied to clipboard
Node.GetVar
The Node does not have GetVar
I have an extension class for Node and UIElement GetVar(string name) and a Variant Reader for Variant returned from GetAttribute() It's not tested much and it is missing some types of Variant but it works on Android 32 and 64 bit and on Windows Desktop. here is the code: https://pastebin.com/n17fkHwF
I didn't have the time to track down how some of the types must be read and i didn't perform any optimization on it.
Anybody who wants to use it, feel free to, just share other Variant getters and let me know if it works at all on iOS
Question for UrhoSharp Developers (or anyone who can explain it)
The code in Variant IntPtrToVariant(this IntPtr ptr) must read all VariantValueLine with an offset of 4 bytes from the previous value line to work, even on 64 bit architectures.
Whitout this function the Variants read from the unmanaged memory (Urho3D) on 64 bit architectures becomes unaligned:
VariantValueLine1 reads the first and second union and VariantValueLine2 reads the third and fourth union
VariantValueLine3 and VariantValueLine4 end up as gibberish.
Why?
@Fastran wow, great job!
is not that offset is a VariantType Type field?
Have you tried to just read Variant as
Marshal.PtrToStructure(ptr, typeof(Variant))
?
I tried Marshal.PtrToStructure(ptr, typeof(Variant)), it works fine on a 32 bit architecture. On a 64 bit architecture for a Variant of type Vector4 it reads the type correctly, VariantValueLine1 was also correct but VariantValueLine2 reads what is supposed to be the third value and VariantValueLine3 and VariantValueLine4 read after the end of the c++ struct.
From what i have seen a Urho3D Variant is always like this in memory
| Field | 32 bit offset | 32 bit size | 64 bit offset | 64 bit size |
|---|---|---|---|---|
| type | 0 | 4 | 0 | 4 |
| Value1 | 4 | 4 | 8 | 8 |
| Value2 | 8 | 4 | 12 | 8 |
| Value3 | 12 | 4 | 16 | 8 |
| Value4 | 16 | 4 | 20 | 8 |
I really can't understand the strange alignment of variables on the 64 bit architecture, the only thing that comes to mind is if it can derive from how Urho3D is compiled to be used on Xamarin, but i don't know anything of how that works
Edit
The table i've written before is wrong. I think the problem arises because the c++ code basically copies the corresponding object over the structure using the assignment operator i.e.
*(reinterpret_cast<Vector4*>(&value_)) = rhs;
on 64bit machine, when those data are copied into the variantvalue struct, there is a mismatch between the memory alignment of the copied type(i.e. vector4) and the variantvalue struct: the vector4 components are correctly 32bit wide on both 32 and 64 bit machine (since the components are float) while the c# structure (defined as sequential and composed by intptr) is correctly 8 bytes on a 64bit machine and 4 byte on a 32bit machine. This results on alignment problems depending on the type therefore the reading of each type must be done accordingly. Am i missing something?
Here is the code from before, with a couple of correction and the rest of the types, albeit some untested (the ones marked as obsolete). https://pastebin.com/KKjVqnw8 At the moment i can't test it on iOS but i don't see why it shouldn't work there.
Correction
static public void PrintVariant(this Variant v)
{
var dummy = v.GetValue();
try
{
Debug.WriteLine(v.Type + " " + dummy);
}
finally { }
}
should be
static public void PrintVariant(this Variant v)
{
dynamic dummy = v.GetValue();
try
{
System.Diagnostics.Debug.WriteLine(v.Type+" "+dummy);
}
finally { }
}
Hi! I use UrhoSharp.1.8.91
public static float GetVarFloat(this Node node, string name) {
float res = 0f;
var map = node.GetAttribute("Variables").Value;
var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(map));
Marshal.StructureToPtr(map, ptr, false);
var data = new EventDataContainer(ptr);
res = data.get_float(new StringHash(name).Code);
Marshal.FreeHGlobal(ptr);
return res;
}
this code works on Windows 64, but fails on Android 32, just throws it out of the application