跳到主要内容

桥接函数

HybridCLR的interpreter与AOT之间需要双向函数调用。比如interpreter调用AOT函数,或者AOT通过interface接口或者delegate回调interpreter。

AOT部分与解释器部分的参数传递和存储方式是不同的。解释器部分调用AOT函数,解释器的参数全在解释器栈上,必须借助合适的办法才能将解释器的函数参数传递给AOT函数。同样的,解释器无法直接获得AOT回调函数的参数。必须为每一种签名的函数生成对应的桥接函数,来实现解释器与aot部分的双向函数参数传递。interpreter -> AOT 方向的调用,虽然可以通过ffi之类的库来完成,但函数调用的成本过高,最合理的方式仍然是提前生成好这种双向桥接函数。解释器内部调用直接走解释器栈,不需要桥接函数。

提示

根据桥接函数的原理,对于固定的AOT部分,桥接函数集是确定的,后续无论进行任何热更新,都不会需要新的额外桥接函数。因此不用担心热更上线后突然出现桥接函数缺失的问题。

桥接函数签名

桥接函数必须提前在AOT部分生成,这点跟lua的wrapper函数原理相似。

为了给每个AOT <-> interpreter之间调用的函数找到对应的桥接函数,必须有一种计算函数签名的方式。另外,参数类型和返回值类型完全等效的函数可以共享同一个桥接函数,这极大减少了桥接函数的个数。如下示例,class类型共享相同的签名。因此它们都可以共享一个 object (object, long) 签名的桥接函数。

object Fun1(object a, long b);
string Fun2(string a, long b);
类型签名
sbytei1
byteu1
boolu1
charu2
shorti2
ushortu2
inti4
uintu4
longi8
ulongu8
IntPtri
UintPtru
floatr4
doubler8
class类型u
指针类型u
enum类型underlying 类型对应的签名,如enum Color:short {}的签名为i2
TypedReferencetypedbyref
struct全局唯一struct签名, 类似s{序号}这样

生成桥接函数

com.code-philosophy.hybridclr package中提供工具脚本,推荐使用菜单命令 HybridCLR/Generate/All 自动生成所有桥接函数。你也可以直接使用HybridCLR/Generate/MethodBridge 生成桥接函数,但该命令依赖裁剪后的AOT dll热更新dll,而裁剪后的AOT dll依赖于生成LinkXml生成Il2CppDef。因此如果没有使用HybridCLR/Generate/All命令,必须先依次运行:

  • HybridCLR/Generate/Il2CppDef
  • HybridCLR/Generate/LinkXml
  • HybridCLR/CompileDll/ActiveBuildTarget
  • HybridCLR/Generate/AotDlls
  • HybridCLR/Generate/MethodBridge

平台相关

桥接函数本身是平台无关的。对于同一个dll,所有平台生成的桥接函数文件完全相同。但由于编译宏开关及各平台的基础库(mscorlib之类)不同,导致不同平台生成的桥接函数也不同。因此不要复用桥接函数, 而是每个平台单独生成。