-
-
Notifications
You must be signed in to change notification settings - Fork 381
method_bridge
huatuo的interpreter与AOT之间需要双向函数调用。比如,interpreter调用AOT函数,或者AOT部分有回调函数会调用解释器部分。
AOT部分与解释器部分的参数传递和存储方式是不一样的。比如解释器部分调用AOT函数,解释器的参数全在解释器栈上,必须借助合适的办法才能将解释器的函数参数传递给AOT函数。同样的,解释器无法使用通过办法直接获得AOT回调函数的第x个参数。必须为每一种签名的函数生成对应的桥接函数,来实现解释器与aot部分的双向函数参数传递。
这个操作,虽然可以通过ffi之类的库来完成,但运行时使用这种方式,函数调用的成本过高,因此合理的方式仍然是提前生成好这种双向桥接函数。
解释器内部调用不需要这种桥接函数,可以是任意签名。
不是每一个不同的函数签名都要生成一个桥接函数,大多数签名是可以共享的。例如
int Fun1(int a, int b);
int Fun2(object a, long b);
long Fun3(long a, long b);
object Fun4(object a, object b);
对于x64和arm64平台, int、long、class类型共享相同的签名。因此以上Fun1-Fun4,它们都可以共享一个 "long (long, long) 签名的桥接函数。跟泛型共享规则类型,算出某个函数签名的共享桥接签名后,生成对应的桥接函数。
具体的共享规则是平台相关的,不同的abi的规则不一样。
桥接函数不同于xlua之类生成的wrap函数,大多数情况下添加了新的aot函数是不需要重新生成MethodBridge函数的。
共享规则对函数参数和返回值均生效。
- bool,byte,sbyte,short,char, ushort,int,uint,long,ulong,IntPtr,UIntPtr,class类型,size为1、2、4、8的值类型以及所有引用类型如int&,Vector3& 共享long类型签名
- float、double共享double类型签名
- 其他size的值类型参数使用共用 BigStructureParamAsRef签名
arm64平台由于寄存器众多,导致abi调用约定非常复杂,并且android和ios有微小区别。
- bool,byte,sbyte 共享sbyte签名
- short,ushort,char 共享short签名
- int,uint 共享int签名
- long,ulong,IntPtr,UIntPtr,class类型,size<=8的值类型以及所有引用类型如int&,Vector3& 共享long签名
- float
- double
- size >8且<=16 的共享 s16签名
- Vector2(或者叫HFA2 float) (x,y为float类型)
- Vector3(HFA3 float)
- Vector4(FHA4 float)
- Vector2d (HFA2 double) (即x,y为double类型)
- Vector3d(HFA3 double)
- Vector4d(HFA4 double)
- HVA 2
- HVA 3
- HVA 4
- 剩余size>16的值类型参数共用 BigStructureParamAsRef签名
- size>16的值类型返回值,每个都是独立签名(理论上可以共享,后面再解决)
huatuo已经扫描过Unity核心库和常见的第三方库生成了默认的桥接函数集,相关代码文件为 huatuo/interpreter/MethodBridge_{abi}.cpp,其中{abi}为x64或arm64。
实践项目中总会遇到一些aot函数的共享桥接函数不在默认桥接函数集中。因此提供了Editor工具,根据程序集自动生成所有桥接函数。 代码参见 huatuo_trial 项目
相关生成代码在 Editor/Huatuo/Generators目录。菜单命令代码在Editor/Huatuo/HuatuoEditorHelper.cs中。
菜单 Huatuo/Generate/MethodBridge_x64 生成 MethodBridge_x64.cpp。 Huatuo/Generate/MethodBridge_arm64 生成 MethodBridge_arm64.cpp文件。
将生成好的这两个文件替换 huatuo/interpreter目录下的相应文件即可。
注意!!! 目前扫描工具还不能智能收集泛型类实例的成员函数及泛型函数,因此有可能运行时会出现缺失某些桥接函数。如果发现运行时某个泛型类的函数未能找到对应桥接函数,请手动将错误日志中提示缺失的函数签名加入到MethodBridgeGenerator::PrepareCustomMethodSignatures函数的返回签名列表中。如下:
private List<string> PrepareCustomMethodSignatures()
{
return new List<string>
{
// ExecutionEngineException: GetManaged2NativeMethodPointer. sinature:S108i8i8 not support
"S108i8i8",
};
}