sourcepawn
sourcepawn copied to clipboard
Function casting not working on 1.11
Help us help you
- [x] I have checked that my issue doesn't exist yet.
- [x] I have tried my absolute best to reduce the problem-space and have provided the absolute smallest test-case possible.
- [x] I can always reproduce the issue with the provided description below.
Environment
- Current SourceMod snapshot:
1.11.0.6745
Description
Function casting previously working on the 1.10.0.6512 compiler no longer does on 1.11.
Problematic Code
typedef MyFunc = function void ();
public int Native_Test(Handle hPlugin, int iArgC) {
MyFunc fnFunc = view_as<MyFunc>(GetNativeFunction(1));
}
Expected Behavior
SourcePawn Compiler 1.10.0.6502
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC
C:\Build\SM1.10\scripting\spcomp_function_cast_bug.sp(4) : warning 204: symbol is assigned a value that is never used: "fnFunc"
Code size: 3056 bytes
Data size: 2280 bytes
Stack/heap size: 16384 bytes
Total requirements: 21720 bytes
1 Warning.
Actual Behavior
SourcePawn Compiler 1.11.0.6745
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC
C:\Build\SM1.10\scripting\spcomp_function_cast_bug.sp(4) : error 100: function prototypes do not match
1 Error.
You should not be calling that function returned from GetNativeFunction as a normal function it should be going through Call_StartFunction if I remember correctly.
see: https://sourcemod.dev/#/functions/function.Call_StartFunction
You should not be calling that function returned from
GetNativeFunctionas a normal function it should be going throughCall_StartFunctionif I remember correctly.see: https://sourcemod.dev/#/functions/function.Call_StartFunction
Indeed, I can call the functions just fine via Call_StartFunction on servers running on SM 1.10 and 1.11. It is just the 1.11 compiler misbehaving, so I am sticking with the 1.10 compiler for now until this gets fixed.
It is just the 1.11 compiler misbehaving, so I am sticking with the 1.10 compiler for now until this gets fixed.
I don't think it is, this was an intentional change: #644
Why do you think that it is misbehaving? GetNativeFunction returns a Function and Call_StartFunction takes a Function - it doesn't appear to need to be a MyFunc at any point inside the native handler.
Thanks for pointing that out... indeed this is not the most compelling use case. On the other hand, the aim of that patch was to catch mismatched casts. At the time I assumed there was a special-case for "Function". Apparently there isn't.
I was trying to think of why you'd need this, the only case I could think of: if you want to pass the returned value into a native or something.
I currently have two projects affected by this.
One project is a modular plugin set I am working on where the main plugin calls specific functions defined in a submodule's plugin, but the submodule first has to pass a pointer for one of its functions up to the main module during initialization via a native so it can be stored first.
The second is a project where I have an enum struct containing a function variable that defines a custom action, and that what that function points to is set up during initialization depending on the circumstances and later called. This is done instead of having a huge switch block dispatching to different functions for each case. These functions may originate outside of the plugin like the first one and requires natives to pass functions.
The cast in the example is not needed, though.
But what variable type can I store it as? function is reserved and cannot be used as a type for variable declaration.
"Function" should work.
Oh shit, I did not realize that was a separate thing. Thanks, I can definitely use this.
Is there a way to check or make sure the Function returned by GetNativeFunction match a specific signature similar to typeset / typedef?
Is there a way to check or make sure the
Functionreturned byGetNativeFunctionmatch a specific signature similar totypeset/typedef?
No, the check takes place at the compilation level. Full function signatures (passed argument cell types) are not checked during run time.
You can represent Function by a type from type(set/def) via view_as.
I'm still open to making this cast work because we can add run-time checks for it later on.
The "Function" type vs "function" keyword is unfortunate. It's probably too late to revisit that though.
You can represent
Functionby a type fromtype(set/def)viaview_as.
This stopped working on the 1.11 compiler too:
typedef MyFunc = function void ();
public int Native_Test(Handle hPlugin, int iArgC) {
Function fnFunc = GetNativeFunction(1);
MyFunc fnMyFunc = view_as<MyFunc>(fnFunc);
}
SourcePawn Compiler 1.10.0.6512
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC
C:\Build\SM1.10\scripting\spcomp_function_cast_bug.sp(5) : warning 204: symbol is assigned a value that is never used: "fnMyFunc"
Code size: 3084 bytes
Data size: 2280 bytes
Stack/heap size: 16384 bytes
Total requirements: 21748 bytes
1 Warning.
SourcePawn Compiler 1.11.0.6745
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC
C:\Build\SM1.10\scripting\spcomp_function_cast_bug.sp(5) : error 100: function prototypes do not match
1 Error.
Any updates on this? typedefs are unusable at the moment for situations where typed funcs are downgraded to Function type such as forwards and datapack storage. Workaround is to replace type with base Function type.
I have resorted to passing Function around, ignoring any safety checks offered during compile-time, and then feeling very bad about it afterwards.
Any updates on this?