跳到主要内容

Il2Cpp Dispatch* Indexer

源码: mt/TypeRegistryCommon.cppmt/MetaBinding.cpp
语义权威: ../../spec/metatable/02-INDEX.md


1. 路径

Il2Cpp Player 成员索引走 native Dispatch* C closure:__index / __newindex1 个 upvalueTypeBinding* lightuserdata)。

TypeRegistryCommon.cpp 在填充 IMT/SMT 时调用 FillInstanceMetatable(..., DispatchInstanceIndex, DispatchInstanceNewIndex)

静态类型表 SMT 使用对称的 DispatchStaticIndex / DispatchStaticNewIndex(查 binding->staticMap)。


2. 核心数据结构

2.1 TypeBindingMetaBinding.h

字段用途
Il2CppClass* klass声明类型
NameMetaMap staticMap静态成员:name → MetaInfo
NameMetaMap byobjInstanceMap引用 / struct ByObj 实例成员
NameMetaMap byvalInstanceMapstruct ByVal 实例成员
MethodGroups* ctorGroups构造 overload(不走 indexer)

NameMetaMap = AppendOnlyStringHashMap<MetaInfo>:绑定期写入,运行时只读;key 为成员名字符串(Il2Cpp 持久化 name)。

2.2 MetaInfo

enum class MetaKind { Method, Field, Property }; // Event 已移除

struct MetaInfo {
MetaKind kind;
union {
struct { int closureRef; } method;
FieldMarshalCtx field;
PropertyMarshalCtx property;
};
};
  • Method: closureRef 为 registry 中 direct bridge 或 dispatch closure。
  • Field: FieldMarshalCtx(offset + MarshalMetaInfo* + cs2luaWriter)。
  • Property: PropertyMarshalCtx(getter/setter 函数指针 + sealed 标志)。

3. DispatchInstanceIndex 算法

模板参数:

  • ResolveInstanceMethodTargetFn — 解析 this(ByVal / ByObj 引用 / 引用类型)。
  • MetaTableKind — 选择 byvalInstanceMapbyobjInstanceMap
template <ResolveInstanceMethodTargetFn resolveMethodTarget, MetaTableKind kind>
static int DispatchInstanceIndex(lua_State* L)
{
TypeBinding* binding = (TypeBinding*)lua_touserdata(L, lua_upvalueindex(1));
const char* key = luaL_checkstring(L, 2);
const MetaInfo* info = LookupMeta(map, key);
if (info == nullptr) {
lua_pushnil(L);
return 1;
}
switch (info->kind) {
case MetaKind::Method:
return LuaUtil::PushRef(L, info->method.closureRef);
case MetaKind::Field:
writer(L, fieldPtr, meta); return 1;
case MetaKind::Property:
PropertyBridge::InvokeGetter(L, target, &info->property); return 1;
}
}

与规范对齐:

规范要求Dispatch* 行为
method 直接返回 closurePushRef(closureRef),不 call
field/property 自动 invoke getterC closure 内 call writer/getter
__index misslua_pushnil
method 优先于 field 同名Bind 期 MetaBinding 写入 map 时已消解;lookup 单表

3.1 实例变体入口

C closureMapthis 解析
InstanceByValIndexbyvalInstanceMapResolveByValMethodTarget
InstanceByObjIndexbyobjInstanceMap(值类型 boxed)ResolveByObjValueTypeMethodTarget
InstanceReferenceIndexbyobjInstanceMapResolveByObjReferenceMethodTarget

FillInstanceMetatable 在创建 IMT 时绑定对应 Index/NewIndex 函数对。


4. DispatchInstanceNewIndex

const MetaInfo* info = LookupMeta(map, key);
if (info == nullptr)
return luaL_error(L, "zlua: member not found: %s", key);
// Field → lua2csWriter; Property → PropertyBridge::InvokeSetter
// Method / 无 setter → error

miss 时 strict error(与规范一致)。只读 field(cs2luaWriter == nullptr 且尝试写)在 field 分支报错。


5. Bind 期:MetaBinding

MetaBinding::EnsureBinding(Il2CppClass*)首次 import_type / 触达类型时:

  1. 扁平化 public instance/static 成员到三个 map。
  2. 为每个 method 创建 MethodMarshalCtx;单重载 → CreateDirectMethodClosureRef;多重载 → CreateMethodDispatchClosureRef + MethodGroups
  3. Field/Property 写入 MetaInfoDispatch* 在运行时 lookup 同一份 map。

Event: 不生成 MetaKind::Eventadd_* / remove_* 作为普通 method 进入 map。

Closure upvalue 布局(direct method):

  • [1] ClosureKind(number)
  • [2] TypeBinding*
  • [3] MethodMarshalCtx*

Dispatch closure 额外 upvalue 挂 MethodGroups*


6. 与 TypeRegistryCommon 的协作

函数职责
WriteCommonTypeFields__fullname__typeid__klass
RegisterStaticLiteralFieldsenum/const 直接写类型表 T
FillInstanceMetatable__type__udkind__gcDispatch*
AttachStaticMetatableSMT + __call(构造 dispatch)
PushTypeTable确保 MetaBinding::EnsureBinding 已执行

MetaTableCache 缓存 (Il2CppClass* → IMT ref, SMT ref),避免重复绑表。


7. 热路径成本

每次 obj.field / obj:Method 取成员 时,Dispatch* 固定开销:

  1. Lua:查 mt → 调 C __index closure
  2. C:lua_touserdata + luaL_checkstring + LookupMeta(字符串哈希)
  3. Method 额外:lua_rawgeti(REGISTRY, closureRef)

注意: 本路径 改变 ../../spec/metatable/02-INDEX.md 规定的 Lua 可见语义;仅实现机制不同。


8. 调试

  • LookupMeta miss 返回 nil 时 调用 C# 反射 fallback(规范禁止)。
  • 对照 Mono 行为时,Il2Cpp 与 Mono 的 miss/成员集应一致(Mono 走 Lua 三表 indexer,见 INDEXER-MONO.md)。

9. 相关文件

文件内容
mt/TypeRegistryCommon.cppDispatch* 模板、FillInstanceMetatable
mt/MetaBinding.cppmap 填充、closure ref 创建
mt/InstanceTarget.cppthis / field 地址
bridge/PropertyBridge.cppgetter/setter invoke
marshal/MarshalMeta.cppfield writer 函数指针