Merge pull request #81783 from zaevi/fix-csharp-static-method
C#: make C# static methods accessible.
This commit is contained in:
commit
ce0fa4c691
7 changed files with 104 additions and 4 deletions
|
@ -2353,6 +2353,8 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
|
|||
mi.arguments.push_back(arg_info);
|
||||
}
|
||||
|
||||
mi.flags = (uint32_t)method_info_dict["flags"];
|
||||
|
||||
p_script->methods.set(push_index++, CSharpMethodInfo{ name, mi });
|
||||
}
|
||||
|
||||
|
@ -2602,6 +2604,18 @@ MethodInfo CSharpScript::get_method_info(const StringName &p_method) const {
|
|||
return MethodInfo();
|
||||
}
|
||||
|
||||
Variant CSharpScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
||||
ERR_FAIL_COND_V(!valid, Variant());
|
||||
|
||||
Variant ret;
|
||||
bool ok = GDMonoCache::managed_callbacks.ScriptManagerBridge_CallStatic(this, &p_method, p_args, p_argcount, &r_error, &ret);
|
||||
if (ok) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return Script::callp(p_method, p_args, p_argcount, r_error);
|
||||
}
|
||||
|
||||
Error CSharpScript::reload(bool p_keep_state) {
|
||||
if (!reload_invalidated) {
|
||||
return OK;
|
||||
|
|
|
@ -199,6 +199,7 @@ public:
|
|||
void get_script_method_list(List<MethodInfo> *p_list) const override;
|
||||
bool has_method(const StringName &p_method) const override;
|
||||
MethodInfo get_method_info(const StringName &p_method) const override;
|
||||
Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
|
||||
|
||||
int get_member_line(const StringName &p_member) const override;
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ namespace Godot.SourceGenerators
|
|||
var members = symbol.GetMembers();
|
||||
|
||||
var methodSymbols = members
|
||||
.Where(s => !s.IsStatic && s.Kind == SymbolKind.Method && !s.IsImplicitlyDeclared)
|
||||
.Where(s => s.Kind == SymbolKind.Method && !s.IsImplicitlyDeclared)
|
||||
.Cast<IMethodSymbol>()
|
||||
.Where(m => m.MethodKind == MethodKind.Ordinary);
|
||||
|
||||
|
@ -221,6 +221,29 @@ namespace Godot.SourceGenerators
|
|||
source.Append(" }\n");
|
||||
}
|
||||
|
||||
// Generate InvokeGodotClassStaticMethod
|
||||
|
||||
var godotClassStaticMethods = godotClassMethods.Where(m => m.Method.IsStatic).ToArray();
|
||||
|
||||
if (godotClassStaticMethods.Length > 0)
|
||||
{
|
||||
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
|
||||
source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n");
|
||||
source.Append(" internal new static bool InvokeGodotClassStaticMethod(in godot_string_name method, ");
|
||||
source.Append("NativeVariantPtrArgs args, out godot_variant ret)\n {\n");
|
||||
|
||||
foreach (var method in godotClassStaticMethods)
|
||||
{
|
||||
GenerateMethodInvoker(method, source);
|
||||
}
|
||||
|
||||
source.Append(" ret = default;\n");
|
||||
source.Append(" return false;\n");
|
||||
source.Append(" }\n");
|
||||
|
||||
source.Append("#pragma warning restore CS0109\n");
|
||||
}
|
||||
|
||||
// Generate HasGodotClassMethod
|
||||
|
||||
if (distinctMethodNames.Length > 0)
|
||||
|
@ -356,7 +379,14 @@ namespace Godot.SourceGenerators
|
|||
arguments = null;
|
||||
}
|
||||
|
||||
return new MethodInfo(method.Method.Name, returnVal, MethodFlags.Default, arguments,
|
||||
MethodFlags flags = MethodFlags.Default;
|
||||
|
||||
if (method.Method.IsStatic)
|
||||
{
|
||||
flags |= MethodFlags.Static;
|
||||
}
|
||||
|
||||
return new MethodInfo(method.Method.Name, returnVal, flags, arguments,
|
||||
defaultArguments: null);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace Godot.Bridge
|
|||
public delegate* unmanaged<IntPtr, IntPtr*, godot_bool, godot_bool> ScriptManagerBridge_SwapGCHandleForType;
|
||||
public delegate* unmanaged<IntPtr, delegate* unmanaged<IntPtr, godot_string*, void*, int, void>, void> ScriptManagerBridge_GetPropertyInfoList;
|
||||
public delegate* unmanaged<IntPtr, delegate* unmanaged<IntPtr, void*, int, void>, void> ScriptManagerBridge_GetPropertyDefaultValues;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant**, int, godot_variant_call_error*, godot_variant*, godot_bool> ScriptManagerBridge_CallStatic;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant**, int, godot_variant_call_error*, godot_variant*, godot_bool> CSharpInstanceBridge_Call;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant*, godot_bool> CSharpInstanceBridge_Set;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant*, godot_bool> CSharpInstanceBridge_Get;
|
||||
|
@ -70,6 +71,7 @@ namespace Godot.Bridge
|
|||
ScriptManagerBridge_SwapGCHandleForType = &ScriptManagerBridge.SwapGCHandleForType,
|
||||
ScriptManagerBridge_GetPropertyInfoList = &ScriptManagerBridge.GetPropertyInfoList,
|
||||
ScriptManagerBridge_GetPropertyDefaultValues = &ScriptManagerBridge.GetPropertyDefaultValues,
|
||||
ScriptManagerBridge_CallStatic = &ScriptManagerBridge.CallStatic,
|
||||
CSharpInstanceBridge_Call = &CSharpInstanceBridge.Call,
|
||||
CSharpInstanceBridge_Set = &CSharpInstanceBridge.Set,
|
||||
CSharpInstanceBridge_Get = &CSharpInstanceBridge.Get,
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace Godot.Bridge
|
|||
internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_name* nativeTypeName,
|
||||
IntPtr godotObject)
|
||||
{
|
||||
// TODO: Optimize with source generators and delegate pointers
|
||||
// TODO: Optimize with source generators and delegate pointers.
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -124,7 +124,7 @@ namespace Godot.Bridge
|
|||
IntPtr godotObject,
|
||||
godot_variant** args, int argCount)
|
||||
{
|
||||
// TODO: Optimize with source generators and delegate pointers
|
||||
// TODO: Optimize with source generators and delegate pointers.
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -677,6 +677,8 @@ namespace Godot.Bridge
|
|||
|
||||
methodInfo.Add("params", methodParams);
|
||||
|
||||
methodInfo.Add("flags", (int)method.Flags);
|
||||
|
||||
methods.Add(methodInfo);
|
||||
}
|
||||
}
|
||||
|
@ -958,6 +960,54 @@ namespace Godot.Bridge
|
|||
public godot_variant Value; // Not owned
|
||||
}
|
||||
|
||||
private delegate bool InvokeGodotClassStaticMethodDelegate(in godot_string_name method, NativeVariantPtrArgs args, out godot_variant ret);
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool CallStatic(IntPtr scriptPtr, godot_string_name* method,
|
||||
godot_variant** args, int argCount, godot_variant_call_error* refCallError, godot_variant* ret)
|
||||
{
|
||||
// TODO: Optimize with source generators and delegate pointers.
|
||||
|
||||
try
|
||||
{
|
||||
Type scriptType = _scriptTypeBiMap.GetScriptType(scriptPtr);
|
||||
|
||||
Type? top = scriptType;
|
||||
Type native = GodotObject.InternalGetClassNativeBase(top);
|
||||
|
||||
while (top != null && top != native)
|
||||
{
|
||||
var invokeGodotClassStaticMethod = top.GetMethod(
|
||||
"InvokeGodotClassStaticMethod",
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Static |
|
||||
BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (invokeGodotClassStaticMethod != null)
|
||||
{
|
||||
var invoked = invokeGodotClassStaticMethod.CreateDelegate<InvokeGodotClassStaticMethodDelegate>()(
|
||||
CustomUnsafe.AsRef(method), new NativeVariantPtrArgs(args, argCount), out godot_variant retValue);
|
||||
if (invoked)
|
||||
{
|
||||
*ret = retValue;
|
||||
return godot_bool.True;
|
||||
}
|
||||
}
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.LogException(e);
|
||||
*ret = default;
|
||||
return godot_bool.False;
|
||||
}
|
||||
|
||||
*ret = default;
|
||||
(*refCallError).Error = godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_INVALID_METHOD;
|
||||
return godot_bool.False;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe void GetPropertyDefaultValues(IntPtr scriptPtr,
|
||||
delegate* unmanaged<IntPtr, void*, int, void> addDefValFunc)
|
||||
|
|
|
@ -70,6 +70,7 @@ void update_godot_api_cache(const ManagedCallbacks &p_managed_callbacks) {
|
|||
CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, SwapGCHandleForType);
|
||||
CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, GetPropertyInfoList);
|
||||
CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, GetPropertyDefaultValues);
|
||||
CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, CallStatic);
|
||||
CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Call);
|
||||
CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Set);
|
||||
CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Get);
|
||||
|
|
|
@ -95,6 +95,7 @@ struct ManagedCallbacks {
|
|||
using FuncScriptManagerBridge_SwapGCHandleForType = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, GCHandleIntPtr *, bool);
|
||||
using FuncScriptManagerBridge_GetPropertyInfoList = void(GD_CLR_STDCALL *)(CSharpScript *, Callback_ScriptManagerBridge_GetPropertyInfoList_Add);
|
||||
using FuncScriptManagerBridge_GetPropertyDefaultValues = void(GD_CLR_STDCALL *)(CSharpScript *, Callback_ScriptManagerBridge_GetPropertyDefaultValues_Add);
|
||||
using FuncScriptManagerBridge_CallStatic = bool(GD_CLR_STDCALL *)(const CSharpScript *, const StringName *, const Variant **, int32_t, Callable::CallError *, Variant *);
|
||||
using FuncCSharpInstanceBridge_Call = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *, const Variant **, int32_t, Callable::CallError *, Variant *);
|
||||
using FuncCSharpInstanceBridge_Set = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *, const Variant *);
|
||||
using FuncCSharpInstanceBridge_Get = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *, Variant *);
|
||||
|
@ -130,6 +131,7 @@ struct ManagedCallbacks {
|
|||
FuncScriptManagerBridge_SwapGCHandleForType ScriptManagerBridge_SwapGCHandleForType;
|
||||
FuncScriptManagerBridge_GetPropertyInfoList ScriptManagerBridge_GetPropertyInfoList;
|
||||
FuncScriptManagerBridge_GetPropertyDefaultValues ScriptManagerBridge_GetPropertyDefaultValues;
|
||||
FuncScriptManagerBridge_CallStatic ScriptManagerBridge_CallStatic;
|
||||
FuncCSharpInstanceBridge_Call CSharpInstanceBridge_Call;
|
||||
FuncCSharpInstanceBridge_Set CSharpInstanceBridge_Set;
|
||||
FuncCSharpInstanceBridge_Get CSharpInstanceBridge_Get;
|
||||
|
|
Loading…
Reference in a new issue