我正在 Godot 中为我的游戏制作一个模组系统,模组制作者用 C# 编写代码并将其编译为 DLL,游戏从中加载并执行方法。
compile方法的相关部分(返回一个Assembly)
string dll = //the absolute path...
if (File.Exists(dll)) {
return Assembly.LoadFrom(dll);
}
然后我调用这样的方法:
private void ExecuteModMethod(Mod mod, string methodName, object[] methodParameters)
{
if (!useMods) return;
Type type = mod.Assembly.GetType(mod.Name+".Main");
if (type == null) return;
MethodInfo method = type.GetMethod(methodName);
mod.Instance = Activator.CreateInstance(type);
if (method == null) return;
method.Invoke(mod.Instance, methodParameters);
}
当我尝试调用
_Ready
方法(Godot init 方法,模组作者也应该命名他们的 init 方法)时,我得到 Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
这是模组中唯一的代码文件:
using Godot;
namespace TestMod
{
public class Main
{
//Called when the game is loaded
public void _Ready()
{
GD.Print("Hello from the mod!");
}
}
}
我对 DLL 和此类事情了解不多,因此感谢您的帮助。我只需要错误消失,因为它停止了应用程序的执行,因此没有调用任何方法。
注意事项
type
、method
和mod.Instance
都不为空。这不是问题。戈多的首字母有 3 个
AssemblyLoadContext
:
你的脚本被加载到第二个ALC中,所以你也需要将你的mod程序集加载到这个ALC中,ALC将解析Godot的程序集。
Assembly.LoadFrom
将程序集加载到默认程序集,您需要将其替换为以下代码:
var executingASM = Assembly.GetExecutingAssembly();
var executingALC = AssemblyLoadContext.GetLoadContext(executingASM);
var fullDllPath = Path.GetFullPath(dll);
return executingALC.LoadFromAssemblyPath(fullDllPath);