MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class) { MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr()); ERR_FAIL_NULL_V(mono_object, NULL); // Search constructor that takes a pointer as parameter MonoMethod *m; void *iter = NULL; while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) { if (strcmp(mono_method_get_name(m), ".ctor") == 0) { MonoMethodSignature *sig = mono_method_signature(m); void *front = NULL; if (mono_signature_get_param_count(sig) == 1 && mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) { break; } } } CRASH_COND(m == NULL); Dictionary *new_dict = memnew(Dictionary(p_from)); void *args[1] = { &new_dict }; MonoException *exc = NULL; GDMonoUtils::runtime_invoke(m, mono_object, args, &exc); UNLIKELY_UNHANDLED_EXCEPTION(exc); return mono_object; }
GDMonoProperty::GDMonoProperty(MonoProperty *p_mono_property, GDMonoClass *p_owner) { owner = p_owner; mono_property = p_mono_property; name = mono_property_get_name(mono_property); MonoMethod *prop_method = mono_property_get_get_method(mono_property); if (prop_method) { MonoMethodSignature *getter_sig = mono_method_signature(prop_method); MonoType *ret_type = mono_signature_get_return_type(getter_sig); type.type_encoding = mono_type_get_type(ret_type); MonoClass *ret_type_class = mono_class_from_mono_type(ret_type); type.type_class = GDMono::get_singleton()->get_class(ret_type_class); } else { prop_method = mono_property_get_set_method(mono_property); MonoMethodSignature *setter_sig = mono_method_signature(prop_method); void *iter = NULL; MonoType *param_raw_type = mono_signature_get_params(setter_sig, &iter); type.type_encoding = mono_type_get_type(param_raw_type); MonoClass *param_type_class = mono_class_from_mono_type(param_raw_type); type.type_class = GDMono::get_singleton()->get_class(param_type_class); } attrs_fetched = false; attributes = NULL; }
void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) { params_count = mono_signature_get_param_count(p_method_sig); MonoType *ret_type = mono_signature_get_return_type(p_method_sig); if (ret_type) { return_type.type_encoding = mono_type_get_type(ret_type); if (return_type.type_encoding != MONO_TYPE_VOID) { MonoClass *ret_type_class = mono_class_from_mono_type(ret_type); return_type.type_class = GDMono::get_singleton()->get_class(ret_type_class); } } void *iter = NULL; MonoType *param_raw_type; while ((param_raw_type = mono_signature_get_params(p_method_sig, &iter)) != NULL) { ManagedType param_type; param_type.type_encoding = mono_type_get_type(param_raw_type); MonoClass *param_type_class = mono_class_from_mono_type(param_raw_type); param_type.type_class = GDMono::get_singleton()->get_class(param_type_class); param_types.push_back(param_type); } }
void MonoMethod::cacheSignature() const { MonoMethodSignature* methodSignature = mono_method_signature(mMethod); MonoType* returnType = mono_signature_get_return_type(methodSignature); if (returnType != nullptr) { ::MonoClass* returnClass = mono_class_from_mono_type(returnType); if (returnClass != nullptr) mCachedReturnType = MonoManager::instance().findClass(returnClass); } mCachedNumParameters = (UINT32)mono_signature_get_param_count(methodSignature); if (mCachedParameters != nullptr) { bs_free(mCachedParameters); mCachedParameters = nullptr; } if (mCachedNumParameters > 0) { mCachedParameters = (MonoClass**)bs_alloc(mCachedNumParameters * sizeof(MonoClass*)); void* iter = nullptr; for (UINT32 i = 0; i < mCachedNumParameters; i++) { MonoType* curParamType = mono_signature_get_params(methodSignature, &iter); ::MonoClass* rawClass = mono_class_from_mono_type(curParamType); mCachedParameters[i] = MonoManager::instance().findClass(rawClass); } } mIsStatic = !mono_signature_is_instance(methodSignature); mHasCachedSignature = true; }
void mioMethod::eachArgTypes(const std::function<void(mioType&)>& f) const { if (!mmethod) { return; } MonoMethodSignature *sig = mono_method_signature(mmethod); MonoType *mt = nullptr; gpointer iter = nullptr; while (mt = mono_signature_get_params(sig, &iter)) { mioType miot = mt; f(miot); } }
/* * mono_method_find * * Get method by its name and argument types */ MonoMethod* mono_method_find(MonoClass *klass, char *name, MonoType **params, int nparams) { MonoMethod *method = NULL; MonoType *param_type; MonoMethodSignature *sig; gpointer method_iter = NULL; gpointer param_iter = NULL; int i; while ((method = mono_class_get_methods(klass, &method_iter))) { if (strcmp(mono_method_get_name(method), name)) continue; sig = mono_method_signature(method); if (mono_signature_get_param_count(sig) != nparams) continue; i = 0; while ((param_type = mono_signature_get_params(sig, ¶m_iter))) { if (mono_class_from_mono_type(param_type) != mono_class_from_mono_type(params[i])) break; if (mono_type_is_byref(param_type) != mono_type_is_byref(params[i])) break; i++; } if (i == nparams) { return method; } } return NULL; }
IMonoMethod *CScriptClass::GetMethod(const char *name, IMonoArray *pArgs, bool throwOnFail) { MonoMethodSignature *pSignature = nullptr; void *pIterator = 0; MonoClass *pClass = (MonoClass *)m_pObject; MonoType *pClassType = mono_class_get_type(pClass); MonoMethod *pCurMethod = nullptr; int suppliedArgsCount = pArgs ? pArgs->GetSize() : 0; while (pClass != nullptr) { pCurMethod = mono_class_get_methods(pClass, &pIterator); if(pCurMethod == nullptr) { pClass = mono_class_get_parent(pClass); if(pClass == mono_get_object_class()) break; pIterator = 0; continue; } pSignature = mono_method_signature(pCurMethod); int signatureParamCount = mono_signature_get_param_count(pSignature); bool bCorrectName = !strcmp(mono_method_get_name(pCurMethod), name); if(bCorrectName && signatureParamCount == 0 && suppliedArgsCount == 0) return new CScriptMethod(pCurMethod); else if(bCorrectName && signatureParamCount >= suppliedArgsCount && suppliedArgsCount != 0) { //if(bStatic != (mono_method_get_flags(pCurMethod, nullptr) & METHOD_ATTRIBUTE_STATIC) > 0) //continue; void *pIter = nullptr; MonoType *pType = nullptr; for(int i = 0; i < signatureParamCount; i++) { pType = mono_signature_get_params(pSignature, &pIter); if(mono::object item = pArgs->GetItem(i)) { MonoClass *pItemClass = mono_object_get_class((MonoObject *)item); MonoType *pItemType = mono_class_get_type(pItemClass); MonoTypeEnum itemMonoType = (MonoTypeEnum)mono_type_get_type(pItemType); MonoTypeEnum monoType = (MonoTypeEnum)mono_type_get_type(pType); if(itemMonoType != monoType) { // exceptions: // Anything can be treated as object. if(monoType == MONO_TYPE_OBJECT) {} // The runtime confuses things with value types a lot, so ignore parameters that appear with that type. else if(itemMonoType == MONO_TYPE_VALUETYPE || monoType == MONO_TYPE_VALUETYPE) {} else { if(MonoClass *pMethodParameterClass = mono_type_get_class(pType)) { MonoWarning("Parameter mismatch when searching for method %s in class %s.%s, on parameter %i: Provided type %s.%s does not match expected parameter type %s.%s.", name, mono_class_get_namespace(pClass), mono_class_get_name(pClass), i + 1, mono_class_get_namespace(pItemClass), mono_class_get_name(pItemClass), mono_class_get_namespace(pMethodParameterClass), mono_class_get_name(pMethodParameterClass)); } else { MonoWarning("Parameter mismatch when searching for method %s in class %s.%s, on parameter %i: Provided type %s.%s does not match parameter type.", name, mono_class_get_namespace(pClass), mono_class_get_name(pClass), i + 1, mono_class_get_namespace(pItemClass), mono_class_get_name(pItemClass)); } break; } } } if(i + 1 == suppliedArgsCount) return new CScriptMethod(pCurMethod); } } } if(throwOnFail) { if(IMonoException *pException = GetMonoScriptSystem()->GetCorlibAssembly()->GetException("System", "MissingMethodException", "Failed to locate method %s in class %s", name, GetName())) pException->Throw(); } return nullptr; }
/* * 将由lua传入的参数表转化为void *[]参数表 * L : 含有参数表的lua_State * base : 参数表在lua_State中的起始位置(靠近栈底的一边) * method : 参数表将要应用到的MonoMethod* * * 该调用只针对Static methods, 和 non-Static methods, 不针对generic methods */ static void *call_method (lua_State *L, int base, MonoObject *thiz, MonoMethod *method, MonoObject **ex) { MonoMethodSignature *sig = mono_method_signature (method); if (!sig) luaL_error (L, "can not get the method's signature."); int n = mono_signature_get_param_count (sig); int cur_n = lua_gettop (L) - base + 1; if (cur_n != n) { /*Fixme : mono_method_full_name 的返回值需要显示 g_free*/ luaL_error (L, "%s need %d arguments, but get %d.", mono_method_full_name (method, 1), n, cur_n); } void **args = 0; if (n > 0) args = new void*[n]; void *iter = 0; MonoType *param_type; for (int i = 0; (param_type = mono_signature_get_params (sig, &iter)) != 0; i++) { /*reference 类型的参数 无论是否加ref关键字, 都是传递改类型对象指针的指针*/ if (mono_type_is_reference (param_type) || mono_type_is_byref (param_type)) { void *p = lua_touserdata (L, base + i); if (!p) luaL_error (L, "%s : %d arg need a reference type.", mono_method_full_name (method, 1), i); args[i] = p; continue; } /*剩下的都是value类型*/ switch (mono_type_get_type (param_type)) { case MONO_TYPE_BOOLEAN: { int b = lua_toboolean (L, base + i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_boolean_class (), &b); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_CHAR: { /*char 用int来表示*/ int b = luaL_checkint (L, base + i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_char_class (), &b); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_I1: { int b = luaL_checkint (L, base + i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_sbyte_class (), &b); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_U1: { unsigned long l = luaL_checkunsigned (L, base + i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_byte_class (), &l); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_I2: { int b = luaL_checkint (L, base + i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_int16_class (), &b); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_U2: { unsigned long l = luaL_checkunsigned (L, base + i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_uint16_class (), &l); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_I4: { int b = luaL_checkint (L, base + i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_int32_class (), &b); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_VALUETYPE: case MONO_TYPE_U4: { unsigned long l = luaL_checkunsigned (L, base + i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_uint32_class (), &l); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_I8: { void *u = lua_touserdata (L, base + i); if (!u) luaL_error (L, "%s : %d arg need Int64.", mono_method_full_name (method, 1), i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_int64_class (), u); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_U8: { void *u = lua_touserdata (L, base + i); if (!u) luaL_error (L, "%s : %d arg need UInt64.", mono_method_full_name (method, 1), i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_uint64_class (), u); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_R4: { /*这里的精度损失由使用lua的人负责*/ float f = (float)lua_tonumber (L, base + i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_single_class (), &f); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_R8: { double d = (double)lua_tonumber (L, base + i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_double_class (), &d); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_I: { void *u = lua_touserdata (L, base + i); if (!u) luaL_error (L, "%s : %d arg need IntPtr.", mono_method_full_name (method, 1), i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_intptr_class (), u); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_U: { void *u = lua_touserdata (L, base + i); if (!u) luaL_error (L, "%s : %d arg need UIntPtr.", mono_method_full_name (method, 1), i); MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_uintptr_class (), u); args[i] = mono_object_unbox (obj); break; } case MONO_TYPE_MVAR: luaL_error (L, "generic method dont be supported."); case MONO_TYPE_PTR: luaL_error (L, "dont support the ptr type."); default: luaL_error (L, "unknow method args type : 0x%02X", mono_type_get_type (param_type)); } } MonoObject *ret = mono_runtime_invoke (method, thiz, args, ex); //MonoType *ret_type = mono_signature_get_return_type (sig); LOGD ("call_method be called!"); return ret; }