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); } }
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; }
int CScriptMethod::GetParameterCount() { if(m_pMonoMethodSignature == nullptr) m_pMonoMethodSignature = mono_method_signature(m_pMonoMethod); return mono_signature_get_param_count(m_pMonoMethodSignature); }
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; }
MonoMethod *CScriptClass::GetMonoMethod(const char *methodName, int numParams) { MonoMethodSignature *pSignature = nullptr; void *pIterator = 0; MonoClass *pClass = (MonoClass *)m_pObject; MonoType *pClassType = mono_class_get_type(pClass); MonoMethod *pCurMethod = nullptr; 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), methodName); if(bCorrectName && signatureParamCount == numParams) return pCurMethod; } return nullptr; }
GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method) { MonoMethodSignature *sig = mono_method_signature(p_raw_method); int params_count = mono_signature_get_param_count(sig); StringName method_name = mono_method_get_name(p_raw_method); return get_method(p_raw_method, method_name, params_count); }
void CPipeServer::GetMethodSignature() { void *method = (void *)ReadQword(); void *methodsignature = mono_method_signature(method); char *sig = mono_signature_get_desc(methodsignature, TRUE); int paramcount = mono_signature_get_param_count(methodsignature); char **names=(char **)calloc(sizeof(char *), paramcount); int i; mono_method_get_param_names(method, (const char **)names); WriteByte(paramcount); for (i = 0; i < paramcount; i++) { if (names[i]) { WriteByte(strlen(names[i])); Write(names[i], strlen(names[i])); } else WriteByte(0); } free(names); WriteWord(strlen(sig)); Write(sig, strlen(sig)); g_free(sig); //12/5/2014:send the returntype as well void *returntype = mono_signature_get_return_type(methodsignature); if (returntype) { char *tname = mono_type_get_name(returntype); if (tname) { WriteByte(strlen(tname)); Write(tname, strlen(tname)); g_free(tname); } else WriteByte(0); } else WriteByte(0); }
IMonoMethod *CScriptClass::GetMethod(const char *name, int numParams, bool throwOnFail) { MonoMethodSignature *pSignature = nullptr; void *pIterator = 0; MonoClass *pClass = (MonoClass *)m_pObject; MonoType *pClassType = mono_class_get_type(pClass); MonoMethod *pCurMethod = nullptr; 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 == numParams) return new CScriptMethod(pCurMethod); } if(throwOnFail) { if(!GetMonoScriptSystem()->IsInitialized()) { CryLogAlways("Failed to locate method %s in class %s", name, GetName()); } else if(IMonoAssembly *pCorlibAssembly = GetMonoScriptSystem()->GetCorlibAssembly()) { if(IMonoException *pException = GetMonoScriptSystem()->GetCorlibAssembly()->GetException("System", "MissingMethodException", "Failed to locate method %s in class %s", name, GetName())) pException->Throw(); } } return nullptr; }
int CScriptClass::GetMethods(const char *name, int numParams, IMonoMethod ***pMethodsOut, int maxMethods, bool throwOnFail) { MonoMethodSignature *pSignature = nullptr; void *pIterator = 0; int i = 0; MonoClass *pClass = (MonoClass *)m_pObject; MonoType *pClassType = mono_class_get_type(pClass); MonoMethod *pCurMethod = nullptr; 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 == numParams) { *pMethodsOut[i] = new CScriptMethod(pCurMethod); i++; if(i == maxMethods) return i + 1; } } return i + 1; }
/* * 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; }
int mioMethod::getParamCount() const { if (!mmethod) { return -1; } MonoMethodSignature *sig = mono_method_signature(mmethod); return mono_signature_get_param_count(sig); }