- Home /
The question is answered, right answer was accepted
Haxe typedef cast to something meaningful in C#
I have a quite serious headache. A middle-ware library has been developed for my project in Haxe (http://haxe.org/ ). Basically haxe is a meta language, to help cross platform and cross language development. The problem is, the creator of the library used a lot of typedef-s which is a handy tool for avoiding a lot of class declarations (http://haxe.org/manual/type-system-typedef.html ). The problem is, that the data sent in this structure has a type Object. If I print it out it looks like a JSON or a JS object.
{ rounds : 804, strength : NaN, efficiency : NaN, win_ratio : NaN }
If you have any Idea or experience in dealing with such data, I would be glad to hear your ideas. Have you tried any auto-map library in unity so far? Thanks!
Update:
As @Bunny83 suggested I gathered more information. The library was build to form a layer between the server and the client, to avoid direct server calls from the client side code. Our library is a .NET assembly and it is part of the Unity project, so I have access to the source, and I could look up the calling method. The actual type is "DynamicObject" which is not particularly helpful here. As I went after the calling method. I have found that, the return type is actually haxe.ds.EnumValueMap which is a class made up by the haxe cross-compiler, and cast to DynamicObject.
return (((global::haxe.ds.EnumValueMap<object, object>) (global::haxe.ds.EnumValueMap<object, object>.__hx_cast<object, object>(((global::haxe.ds.EnumValueMap) (global::haxe.lang.Runtime.getField(p, "game_stats", 232010450, true)) ))) ).@get(t)).toDynamic();
In this point I don't really know what to expect from you, I guess I have to Implement the cast from the EnumValueMap to a dictionary.
The haxe code is this in this particular example:
typedef GameStat = {
rounds: Int,
win_ratio: Float,
strength: Float,
efficiency: Float
}
Answer by Bunny83 · Jun 04, 2015 at 11:46 PM
First of all the type of the object most likely isn't "object". The method might return a reference of type "object" but the actual instance probably has a different type. When you "print" / "Debug.Log" the reference Unity just uses the ToString method of that object. So currently we don't know if the object reference referes to a string in JSON format or if it's a custom class instance which has an overridden ToString method which returns the data it contains as some sort of JSON. "NaN" usually isn't an allowed value in JSON so it might only be just a string representation of the actual class.
You should try to figure out which type the actual value has and if you have access to that class. Just call the "GetType()" method on your object and read the "Name" property:
// C#
object yourReference;
Debug.Log("Type is: " + yourReference.GetType().Name);
This should tell you the classname of the actual class.
As far as i understood that meta language actually has cross compilers for different platforms. If the library actually is a .NET assembly you can simply view and inspect the Assembly by using a reflector like ILSpy. ILSpy allows you to view the code in IL (.NET / Mono Intermediate Language), C# or VB.NET
If the library is a .NET assembly and part of your Unity project, MonoDevelop and VisualStudio should recognise it's containing namespaces / classes and provide autocomplete as long as the type is known.
We can't tell you how to "use" that library since we have way less information than you have. We don't even know what this library is good for. A library without a documentation is pretty pointless / useless.
Thank you for your help, I have updated the question according to your suggestions. And yes a library without good documentation is quite useless, but this is what I have. The documentation is under construction, by the author, but I am pushed, to work with the actual code, to meet deadlines.
Well, the actual returned class instance has to be a .NET class as well. It might be defined in another .NET dll that ships with the crosscompiler. Just like in Unity where your scripts are compiled to a seperate DLL (Assembly-CSharp.dll or Assembly-UnityScript.dll) your dll depends on the UnityEngine.dll which defines classes and structs like Vector3, GameObject, ...
If the library depends on such a framework dll it also has to be located in your project. Your best friend with unknown libraries is a reflector. That EnumValue$$anonymous$$ap class has to be defined somewhere. It's most likely just a custom implementation of some sort of dictionary / associative array.
Have you tried if the class has some indexers like a dictionary?
You are right, it is a mixed type Dictionary implementation, without basically any way to access the data. It has no indexers and doesn't implement an iterator. The cross-compiled source looks more like machine code than actual c# (ok not really). If you are interested here is the class deffinition.
Well, i never used Haxe but from the documentation of the standard library the EnumValue$$anonymous$$ap class is derived from BalancedTree which has iterators for it's keys, values and also a get accessor.
Since C# / .NET is a strong typed lanugage / environment you might have to cast a lot things to their right type before you can use it properly.
ps: The class definition is normal C#, but it's not well formatted which makes it hard to read. But even in that definition you can see that it's derived from haxe.ds.BalancedTree.
Finally it turned out that the haxe DynamicObject has a __hx_getField() method. That somehow escaped me for now. The misunderstanding was due to the fact, that haxe overrides the DynamicObject class if I understand it properly. It turned out that you can access these with a simple methodcall like this:
DynamicObject _tmp = (DynamicObject) Player.getGameStats(Player.self.id, GameStatType.HOLDE$$anonymous$$_TOTAL.toString() ) ;
print (_tmp.__hx_getField("rounds",_tmp.__hx_hashes[0],true,true,true) + " Rounds played!");
Any further advice is welcomed, and thanks for @Bunny83 for the atention.