bmx-ng / brl.mod

BlitzMax Runtime Libraries, for BlitzMax NG.
12 stars 12 forks source link

[brl.reflection] Method/Function invocation params wrong #147

Open GWRon opened 5 years ago

GWRon commented 5 years ago
SuperStrict
Framework Brl.StandardIO
Import Brl.Reflection

Type TTest
    Function DoubleFunc:Int(p:Double)
        Print "DoubleFunc(" + p + ")"
    End Function

    Method DoubleMethod:Int(p:Double)
        Print "DoubleMethod(" + p + ")"
    End Method
End Type

Local t:TTypeId = TTypeId.ForName("TTest")
Local params:Object[] = [String(1.234)]
'works (edit: only in x64)
t.FindFunction("DoubleFunc").Invoke(params)

'fails
Local test:TTest = New TTest
t = TTypeId.ForObject(test)
t.FindMethod("DoubleMethod").Invoke(test, params)

Output:

Executing:untitled3.exe
DoubleFunc(1.0000000000000000)
DoubleMethod(0.00000000000000000)
GWRon commented 5 years ago

Above is the output for "x64". Now I tried with "x86" and it seems that it fails then for "func" too - so I assume it has to do with some memory offsets borking up the whole thing.

DoubleFunc(1.0958905144569552e-301)
DoubleMethod(2.1838914951119074e-307)

PS: this explains why in TVTower the AI assumes too less audience for their shows ;-) (in NG, as in "vanilla" I use grables extended reflection - where it works as the approach is different and x86 only).

GWRon commented 5 years ago

For integers and floats it seems to work:

SuperStrict
Framework Brl.StandardIO
Import Brl.Reflection

Type TTest
    Function IntFunc:Int(i:Int)
        Print "IntFunc(" + i + ")"
    End Function

    Method IntMethod:Int(i:Int)
        Print "IntMethod(" + i + ")"
    End Method

    Function FloatFunc:Int(f:Float)
        Print "FloatFunc(" + f + ")"
    End Function

    Method FloatMethod:Int(f:Float)
        Print "FloatMethod(" + f + ")"
    End Method

    Function DoubleFunc:Int(p:Double)
        Print "DoubleFunc(" + p + ")"
    End Function

    Method DoubleMethod:Int(p:Double)
        Print "DoubleMethod(" + p + ")"
    End Method
End Type

Local test:TTest = New TTest
Local t:TTypeId = TTypeId.ForObject(test)
Local params:Object[] = ["1.234"]
'works (only in x64)
t.FindFunction("DoubleFunc").Invoke(params)
'fails (for x86 and x64)
t.FindMethod("DoubleMethod").Invoke(test, params)

'truncates float to int
params = ["1.234"]
t.FindFunction("FloatFunc").Invoke(params)
t.FindMethod("FloatMethod").Invoke(test, params)

'works
params = ["1"]
t.FindFunction("IntFunc").Invoke(params)
t.FindMethod("IntMethod").Invoke(test, params)
x64:
DoubleFunc(1.2340000000000000)
DoubleMethod(0.00000000000000000)
FloatFunc(1.23399997)
FloatMethod(1.23399997)
IntFunc(1)
IntMethod(1)

x86:
DoubleFunc(1.5064582928911518e-294)
DoubleMethod(2.1913541299095741e-307)
FloatFunc(1.23399997)
FloatMethod(1.23399997)
IntFunc(1)
IntMethod(1)
GWRon commented 5 years ago

Will have to check thoroughly ... as it does not happen on my Linux box.

Edit: Windows 10 + brl/pub/bcc updated (replaced so ... freshly compiled everything). And it is still failing.

GWRon commented 5 years ago

As Float and Int params (and Long etc too) work but not Double - might it need a different size on Windows platforms (in _push()) ? The params passed to it (and converted with ToString().ToDesiredType()) seem to be correct.

HurryStarfish commented 5 years ago

Sorry... these kinds of problems should all get fixed (if they aren't already) with the improvements to the BRL.Reflection I've been working on, but I really haven't gotten around to doing anything BlitzMax-related lately (and won't for another week or so). I'll look into this when I can.

GWRon commented 5 years ago

I know about your plans for brl.reflection and am kind of excited to see it come alive. Yet I better opened an issue for this as the bug might be something unrelated to reflection but to pointers or such stuff. Especially as it works on Linux but not Windows.

GWRon commented 5 years ago

Edit: Running the same thing on my Windows10 notebook (Rather than in a VM) results in

Executing:reflection.debug.exe
DoubleFunc(2.3850065506289703e-317)
DoubleMethod(2.3847145578322782e-317)
FloatFunc(6.76449789e-039)
FloatMethod(6.76366972e-039)
IntFunc(1)
IntMethod(1)

Executing:reflection.exe
DoubleFunc(1.2340000000000000)
DoubleMethod(0.00000000000000000)
FloatFunc(1.23399997)
FloatMethod(0.000000000)
IntFunc(1)
IntMethod(1)

So also "float" is affected, not just "double".

As it differs between "release" and "debug" stuff might have to do with the internal structure of types and functions and fields ?

@HurryStarfish or @woollybah Do you have an idea (next to passing a "multiply with 100000" long to avoid the floating points) how to fix that (must not be "perfect" or might be a custom function to call stuff outside of the reflection.mod). As this is a crucial functionality I use for the Lua scripts of my AI and if this doesn't do I either need to use "legacy" again (it works for now) or to completely rewrite a lot of portions in the AI scripts and surely still miss parts and will then enjoy incoming reports about dumb AI players :)

As I am aware of the brl.reflection changes I am not sure if this should be "fixed" if it requires a lot of changes while the new reflection code already lurks around the corner,