跳到主要内容

HybridCLR+lua/js/python

有一些项目已经上线,它们的大多数代码已经用lua实现了;或者一些新项目已经用lua开发到一半,他们无法完全切换为全C#开发,但希望 可以同时接入HybridCLR,帮助慢慢过渡到全部原生C#热更新。由于HybridCLR是原生C#热更新技术,原生支持与这些脚本语言配合工作。

提示

你要做的,仅仅是将那些要热更新wrapper文件生成到热更新模块,同时提前预留足够多的ReversePInvoke函数。

xlua

xlua并未考虑过模块化,生成的代码全在全局Assembly-CSharp里,甚至做成partial类与Runtime代码关联,因此你可能需要对这些热更新方案的生成代码做少量调整,才能与热更新配合工作。 已经有群友制作了 HybridCLR+xlua 的项目 HybridCLRXlua,已经跑通。没有充分理解的开发者可以借鉴学习。

tolua、slua、puerts

确保预留了足够多的ReversePInvokeWrapper函数并且生成的wrapper代码能放到热更新模块,并且正确注册即可。

MonoPInvokeCallbackAttribute支持

HybridCLR对 [MonoPInvokeCallbackAttribute] 的支持跟原生完全相同。由于每个标注 [MonoPInvokeCallbackAttribute] 的函数必须有一个唯一对应的c++函数,而AOT限制导致不可能运行时新增函数, 因而要提前为每个[MonoPInvokeCallbackAttribute]函数生成一个c++ wrapper函数,用于与之绑定。这些wrapper函数在 hybridclr/generated/ReversePInvokeMethodStub_{abi}.cpp 文件中。

com.code-philosophy.hybridclr 已经提供了脚本帮助自动生成这些wrapper函数,运行菜单命令HybridCLR/Generate/ReversePInvokeWrapper 即可。

预留 ReversePInvokeWrapper 函数

HybridCLR/Generate/ReversePInvokeWrapper默认为每个带[MonoPInvokeCallbackAttribute]特性的函数生成一个wrapper函数。 但如果仅仅生成跟当前拥有[MonoPInvokeCallbackAttribute]特性的函数相同个数的wrapper函数,后面新增热更新函数则 会发生wrapper函数不足的问题。解决方法是使用HybridCLR.ReversePInvokeWrapperGenerationAttribute进行预留操作。

在带有MonoPInvokeCallbackAttribute的函数上新增一个特性 [ReversePInvokeWrapperGeneration(int preserveCount)],则为这个签名的函数生成preserveCount个wrapper函数。如果不包含此特性,则只会为这个函数生成 一个wrapper函数。如果对多个相同签名的函数添加了[ReversePInvokeWrapperGeneration(xx)] 特性,则wrapper函数总数为 所有 preserveCount之和 + 不包含 ReversePInvokeWrapperGenerationAttribute 特性的函数个数

如下如示, LuaFunction 类型的wrapper有10个, Func<int, int, int> 类型的wrapper有101个,Func<int, int> 类型的wrapper有1个。


delegate int LuaFunction(IntPtr luaState);

public class MonoPInvokeWrapperPreserves
{
[ReversePInvokeWrapperGeneration(10)]
[MonoPInvokeCallback(typeof(LuaFunction))]
public static int LuaCallback(IntPtr luaState)
{
return 0;
}

[ReversePInvokeWrapperGeneration(100)]
[MonoPInvokeCallback(typeof(Func<int, int, int>))]
public static int Sum(int a, int b)
{
return a + b;
}

[MonoPInvokeCallback(typeof(Func<int, int, int>))]
public static int Sum2(int a, int b)
{
return a + b;
}

[MonoPInvokeCallback(typeof(Func<int, int>))]
public static int Inc(int a)
{
return a + 1;
}
}

限制

警告

请确保函数参数都是简单primitive类型如int、float之类。

目前没有对引用类型参数作marshal处理,诸如string之类引用类型的参数都是直接传参处理,使用后必然会导致崩溃! 如果实在有这种需求,可以将回调函数放到AOT中,在AOT中再回调热更新 函数。