Value RuntimeObjectImp::get(ExecState *exec, const Identifier &propertyName) const { Value result = Undefined(); instance->begin(); Class *aClass = instance->getClass(); if (aClass) { // See if the instance have a field with the specified name. Field *aField = aClass->fieldNamed(propertyName.ascii(), instance); if (aField) { result = instance->getValueOfField (exec, aField); } else { // Now check if a method with specified name exists, if so return a function object for // that method. MethodList methodList = aClass->methodsNamed(propertyName.ascii(), instance); if (methodList.length() > 0) { result = Object (new RuntimeMethodImp(exec, propertyName, methodList)); } } if (result.type() == UndefinedType) { // Try a fallback object. result = aClass->fallbackObject (exec, instance, propertyName); } } instance->end(); return result; }
MethodList BalClass::methodsNamed(const Identifier& identifier, Instance* instance) const { MethodList methodList; Method* method = m_methods.get(identifier.ustring().rep()); if (method) { methodList.append(method); return methodList; } const char *ident = identifier.ascii(); const BalInstance* inst = static_cast<const BalInstance*>(instance); BalObject* obj = inst->getObject(); if( obj->hasMethod( ident ) ) { Method* aMethod = new BalMethod(ident); // deleted in the CClass destructor { JSLock lock(false); m_methods.set(identifier.ustring().rep(), aMethod); } methodList.append(aMethod); } return methodList; }
MethodList EAClass::methodsNamed(const Identifier& identifier, Instance* instance) const { MethodList methodList; // Check to see if the method has been cached first. Method* method = mMethods.get(identifier.impl()); if (method) { methodList.append(method); return methodList; } // Method hasn't been called before, see if the object supports it. // Rather than doing identifier.ascii().data(), we need to create CString separately otherwise it goes out of scope. CString identStr = identifier.ascii(); const char *ident = identStr.data(); const EAInstance *inst = static_cast<const EAInstance*>(instance); EA::WebKit::IJSBoundObject *obj = inst->getObject(); if (obj->hasMethod(ident)) { // The object says it has this method, cache it so that the string // lookup can be avoided in the future. EAMethod* aMethod = new EAMethod(ident); { JSLock lock(SilenceAssertionsOnly); mMethods.set(identifier.impl(), aMethod); } methodList.append(aMethod); } return methodList; }
MethodList BalClass::methodsNamed(const Identifier& identifier, Instance* instance) const { MethodList methodList; Method* method = m_methods.get(identifier.ustring().rep()); if (method) { methodList.append(method); return methodList; } const UChar* ident16 = identifier.ustring().data(); char ident[256]; sprintf(ident,"%S",ident16); ident[identifier.ustring().size()] = '\0'; const BalInstance* inst = static_cast<const BalInstance*>(instance); BalObject* obj = inst->getObject(); if( obj->hasMethod( ident ) ) { BalMethod *aMethod= new BalMethod(obj, 0, ident, 0); m_methods.set(identifier.ustring().rep(), aMethod); methodList.append(aMethod); } return methodList; }
JavaClass::JavaClass(jobject anInstance) { jobject aClass = callJNIMethod<jobject>(anInstance, "getClass", "()Ljava/lang/Class;"); if (!aClass) { LOG_ERROR("Unable to call getClass on instance %p", anInstance); m_name = fastStrDup("<Unknown>"); return; } if (jstring className = (jstring)callJNIMethod<jobject>(aClass, "getName", "()Ljava/lang/String;")) { const char* classNameC = getCharactersFromJString(className); m_name = fastStrDup(classNameC); releaseCharactersForJString(className, classNameC); } else m_name = fastStrDup("<Unknown>"); int i; JNIEnv* env = getJNIEnv(); // Get the fields if (jarray fields = (jarray)callJNIMethod<jobject>(aClass, "getFields", "()[Ljava/lang/reflect/Field;")) { int numFields = env->GetArrayLength(fields); for (i = 0; i < numFields; i++) { jobject aJField = env->GetObjectArrayElement((jobjectArray)fields, i); JavaField* aField = new JavaField(env, aJField); // deleted in the JavaClass destructor { JSLock lock(SilenceAssertionsOnly); m_fields.set(((UString)aField->name()).rep(), aField); } env->DeleteLocalRef(aJField); } env->DeleteLocalRef(fields); } // Get the methods if (jarray methods = (jarray)callJNIMethod<jobject>(aClass, "getMethods", "()[Ljava/lang/reflect/Method;")) { int numMethods = env->GetArrayLength(methods); for (i = 0; i < numMethods; i++) { jobject aJMethod = env->GetObjectArrayElement((jobjectArray)methods, i); JavaMethod* aMethod = new JavaMethod(env, aJMethod); // deleted in the JavaClass destructor MethodList* methodList; { JSLock lock(SilenceAssertionsOnly); methodList = m_methods.get(((UString)aMethod->name()).rep()); if (!methodList) { methodList = new MethodList(); m_methods.set(((UString)aMethod->name()).rep(), methodList); } } methodList->append(aMethod); env->DeleteLocalRef(aJMethod); } env->DeleteLocalRef(methods); } env->DeleteLocalRef(aClass); }
void Package::addMethod(Method *mtd) { assert(mtd && "ERROR!!: Method is NULL\n"); MethodList *list = (mtds->exists(mtd->subname)) ? mtds->get(mtd->subname) : new MethodList(); list->add(mtd); mtds->add(MethodMap::value_type(mtd->subname, list)); }
JavaClassJobject::JavaClassJobject(jobject anInstance, bool requireAnnotation) : m_requireAnnotation(requireAnnotation) #else JavaClassJobject::JavaClassJobject(jobject anInstance) #endif { jobject aClass = callJNIMethod<jobject>(anInstance, "getClass", "()Ljava/lang/Class;"); if (!aClass) { LOG_ERROR("unable to call getClass on instance %p", anInstance); return; } JNIEnv* env = getJNIEnv(); // Get the fields jarray fields = static_cast<jarray>(callJNIMethod<jobject>(aClass, "getFields", "()[Ljava/lang/reflect/Field;")); int numFields = env->GetArrayLength(fields); for (int i = 0; i < numFields; i++) { jobject aJField = env->GetObjectArrayElement(static_cast<jobjectArray>(fields), i); JavaField* aField = new JavaFieldJobject(env, aJField); // deleted in the JavaClass destructor m_fields.set(aField->name(), aField); env->DeleteLocalRef(aJField); } // Get the methods jarray methods = static_cast<jarray>(callJNIMethod<jobject>(aClass, "getMethods", "()[Ljava/lang/reflect/Method;")); int numMethods = env->GetArrayLength(methods); #if PLATFORM(ANDROID) jmethodID isAnnotationPresentMethodID = getAnnotationMethodID(env); if (!isAnnotationPresentMethodID) { LOG_ERROR("unable to find method %s on instance %p", kIsAnnotationPresent, anInstance); return; } #endif for (int i = 0; i < numMethods; i++) { jobject aJMethod = env->GetObjectArrayElement(static_cast<jobjectArray>(methods), i); #if PLATFORM(ANDROID) if (jsAccessAllowed(env, isAnnotationPresentMethodID, aJMethod)) { #endif JavaMethod* aMethod = new JavaMethodJobject(env, aJMethod); // deleted in the JavaClass destructor MethodList* methodList = m_methods.get(aMethod->name()); if (!methodList) { methodList = new MethodList(); m_methods.set(aMethod->name(), methodList); } methodList->append(aMethod); #if PLATFORM(ANDROID) } #endif env->DeleteLocalRef(aJMethod); } env->DeleteLocalRef(fields); env->DeleteLocalRef(methods); env->DeleteLocalRef(aClass); }
MethodList QtPixmapClass::methodsNamed(const Identifier& identifier, Instance*) const { MethodList methods; if (identifier == QtPixmapToDataUrlMethod::name()) methods.append(&qt_pixmap_metaData.toDataUrlMethod); else if (identifier == QtPixmapAssignToElementMethod::name()) methods.append(&qt_pixmap_metaData.assignToElementMethod); else if (identifier == QtPixmapToStringMethod::name()) methods.append(&qt_pixmap_metaData.toStringMethod); return methods; }
JavaClass::JavaClass(jobject anInstance) { jobject aClass = callJNIMethod<jobject>(anInstance, "getClass", "()Ljava/lang/Class;"); if (!aClass) { fprintf(stderr, "%s: unable to call getClass on instance %p\n", __PRETTY_FUNCTION__, anInstance); return; } jstring className = (jstring)callJNIMethod<jobject>(aClass, "getName", "()Ljava/lang/String;"); const char *classNameC = getCharactersFromJString(className); _name = strdup(classNameC); releaseCharactersForJString(className, classNameC); int i; JNIEnv *env = getJNIEnv(); JSGlobalData* globalData = WebCore::JSDOMWindow::commonJSGlobalData(); // Get the fields jarray fields = (jarray)callJNIMethod<jobject>(aClass, "getFields", "()[Ljava/lang/reflect/Field;"); int numFields = env->GetArrayLength(fields); for (i = 0; i < numFields; i++) { jobject aJField = env->GetObjectArrayElement((jobjectArray)fields, i); Field *aField = new JavaField(env, aJField); // deleted in the JavaClass destructor { JSLock lock(false); _fields.set(Identifier(globalData, UString(aField->name())).ustring().rep(), aField); } env->DeleteLocalRef(aJField); } // Get the methods jarray methods = (jarray)callJNIMethod<jobject>(aClass, "getMethods", "()[Ljava/lang/reflect/Method;"); int numMethods = env->GetArrayLength(methods); for (i = 0; i < numMethods; i++) { jobject aJMethod = env->GetObjectArrayElement((jobjectArray)methods, i); Method *aMethod = new JavaMethod(env, aJMethod); // deleted in the JavaClass destructor MethodList* methodList; { JSLock lock(false); methodList = _methods.get(Identifier(globalData, UString(aMethod->name())).ustring().rep()); if (!methodList) { methodList = new MethodList(); _methods.set(Identifier(globalData, UString(aMethod->name())).ustring().rep(), methodList); } } methodList->append(aMethod); env->DeleteLocalRef(aJMethod); } }
Method *Package::getMethod(const char *mtd_name) { if (!mtds->size()) return NULL; MethodList *list = mtds->get(mtd_name); MethodList::reverse_iterator it = list->rbegin(); Method *mtd = NULL; while (it != list->rend()) { mtd = *it; if (!mtd->ret) return mtd; it++; } return mtd; }
MethodList QtPixmapClass::methodsNamed(PropertyName identifier, Instance*) const { MethodList methods; UString ustring(identifier.publicName()); if (ustring == QtPixmapToDataUrlMethod::name()) methods.append(&qt_pixmap_metaData.toDataUrlMethod); else if (ustring == QtPixmapToImageDataMethod::name()) methods.append(&qt_pixmap_metaData.toImageDataMethod); else if (ustring == QtPixmapAssignToElementMethod::name()) methods.append(&qt_pixmap_metaData.assignToElementMethod); else if (ustring == QtPixmapToStringMethod::name()) methods.append(&qt_pixmap_metaData.toStringMethod); return methods; }
bool RuntimeObject::getOwnPropertyDescriptor(JSObject* object, ExecState *exec, PropertyName propertyName, PropertyDescriptor& descriptor) { RuntimeObject* thisObject = jsCast<RuntimeObject*>(object); if (!thisObject->m_instance) { throwInvalidAccessError(exec); return false; } RefPtr<Instance> instance = thisObject->m_instance; instance->begin(); Class *aClass = instance->getClass(); if (aClass) { // See if the instance has a field with the specified name. Field *aField = aClass->fieldNamed(propertyName, instance.get()); if (aField) { PropertySlot slot; slot.setCustom(thisObject, fieldGetter); instance->end(); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete); return true; } else { // Now check if a method with specified name exists, if so return a function object for // that method. MethodList methodList = aClass->methodsNamed(propertyName, instance.get()); if (methodList.size() > 0) { PropertySlot slot; slot.setCustom(thisObject, methodGetter); instance->end(); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); return true; } } // Try a fallback object. if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) { PropertySlot slot; slot.setCustom(thisObject, fallbackObjectGetter); instance->end(); descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum); return true; } } instance->end(); return instance->getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); }
bool JavaNPObjectInvoke(NPObject* obj, NPIdentifier identifier, const NPVariant* args, uint32_t argCount, NPVariant* result) { JavaInstance* instance = ExtractJavaInstance(obj); if (!instance) return false; NPUTF8* name = _NPN_UTF8FromIdentifier(identifier); if (!name) return false; instance->begin(); MethodList methodList = instance->getClass()->methodsNamed(name); // TODO: use NPN_MemFree free(name); // Try to find a good match for the overloaded method. The // fundamental problem is that JavaScript doesn't have the // notion of method overloading and Java does. We could // get a bit more sophisticated and attempt to do some // type checking as well as checking the number of parameters. size_t numMethods = methodList.size(); JavaMethod* aMethod; JavaMethod* jMethod = 0; for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) { aMethod = methodList[methodIndex]; if (aMethod->numParameters() == static_cast<int>(argCount)) { jMethod = aMethod; break; } } if (!jMethod) { instance->end(); return false; } JavaValue* jArgs = new JavaValue[argCount]; for (unsigned int i = 0; i < argCount; i++) jArgs[i] = convertNPVariantToJavaValue(args[i], jMethod->parameterAt(i)); JavaValue jResult = instance->invokeMethod(jMethod, jArgs); instance->end(); delete[] jArgs; VOID_TO_NPVARIANT(*result); convertJavaValueToNPVariant(jResult, result); return true; }
void JavaClass::_commonInit (jobject aClass) { long i; JNIEnv *env = getJNIEnv(); // Get the fields jarray fields = (jarray)callJNIObjectMethod (aClass, "getFields", "()[Ljava/lang/reflect/Field;"); long numFields = env->GetArrayLength (fields); _fields = CFDictionaryCreateMutable(NULL, numFields, &kCFTypeDictionaryKeyCallBacks, NULL); for (i = 0; i < numFields; i++) { jobject aJField = env->GetObjectArrayElement ((jobjectArray)fields, i); Field *aField = new JavaField (env, aJField); CFStringRef fieldName = CFStringCreateWithCString(NULL, aField->name(), kCFStringEncodingASCII); CFDictionaryAddValue ((CFMutableDictionaryRef)_fields, fieldName, aField); CFRelease (fieldName); env->DeleteLocalRef (aJField); } // Get the methods jarray methods = (jarray)callJNIObjectMethod (aClass, "getMethods", "()[Ljava/lang/reflect/Method;"); long numMethods = env->GetArrayLength (methods); _methods = CFDictionaryCreateMutable(NULL, numMethods, &kCFTypeDictionaryKeyCallBacks, NULL); for (i = 0; i < numMethods; i++) { jobject aJMethod = env->GetObjectArrayElement ((jobjectArray)methods, i); Method *aMethod = new JavaMethod (env, aJMethod); CFStringRef methodName = CFStringCreateWithCString(NULL, aMethod->name(), kCFStringEncodingASCII); MethodList *methodList = (MethodList *)CFDictionaryGetValue ((CFMutableDictionaryRef)_methods, methodName); if (!methodList) { methodList = new MethodList(); CFDictionaryAddValue ((CFMutableDictionaryRef)_methods, methodName, methodList); } methodList->addMethod (aMethod); CFRelease (methodName); env->DeleteLocalRef (aJMethod); } // Get the constructors jarray constructors = (jarray)callJNIObjectMethod (aClass, "getConstructors", "()[Ljava/lang/reflect/Constructor;"); _numConstructors = env->GetArrayLength (constructors); _constructors = new JavaConstructor[_numConstructors]; for (i = 0; i < _numConstructors; i++) { jobject aConstructor = env->GetObjectArrayElement ((jobjectArray)constructors, i); _constructors[i] = JavaConstructor (env, aConstructor); env->DeleteLocalRef (aConstructor); } }
bool RuntimeObject::getOwnPropertySlot(JSCell* cell, ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { RuntimeObject* thisObject = static_cast<RuntimeObject*>(cell); if (!thisObject->m_instance) { throwInvalidAccessError(exec); return false; } RefPtr<Instance> instance = thisObject->m_instance; instance->begin(); Class *aClass = instance->getClass(); if (aClass) { // See if the instance has a field with the specified name. Field *aField = aClass->fieldNamed(propertyName, instance.get()); if (aField) { slot.setCustom(thisObject, thisObject->fieldGetter); instance->end(); return true; } else { // Now check if a method with specified name exists, if so return a function object for // that method. MethodList methodList = aClass->methodsNamed(propertyName, instance.get()); if (methodList.size() > 0) { slot.setCustom(thisObject, thisObject->methodGetter); instance->end(); return true; } } // Try a fallback object. if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) { slot.setCustom(thisObject, thisObject->fallbackObjectGetter); instance->end(); return true; } } instance->end(); return instance->getOwnPropertySlot(thisObject, exec, propertyName, slot); }
bool RuntimeObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { if (!instance) { throwInvalidAccessError(exec); return false; } instance->begin(); Class *aClass = instance->getClass(); if (aClass) { // See if the instance has a field with the specified name. Field *aField = aClass->fieldNamed(propertyName, instance.get()); if (aField) { slot.setCustom(this, fieldGetter); instance->end(); return true; } else { // Now check if a method with specified name exists, if so return a function object for // that method. MethodList methodList = aClass->methodsNamed(propertyName, instance.get()); if (methodList.size() > 0) { slot.setCustom(this, methodGetter); instance->end(); return true; } } // Try a fallback object. if (!aClass->fallbackObject(exec, instance.get(), propertyName)->isUndefined()) { slot.setCustom(this, fallbackObjectGetter); instance->end(); return true; } } instance->end(); // don't call superclass, because runtime objects can't have custom properties or a prototype return false; }
LuaExportTypeDescriptor::~LuaExportTypeDescriptor() { //释放类方法 for (MethodMap::iterator it = _classMethods.begin(); it != _classMethods.end(); it++) { MethodList methodList = it -> second; for (MethodList::iterator mit = methodList.begin(); mit != methodList.end(); mit++) { (*mit) -> release(); } } //释放实例方法 for (MethodMap::iterator it = _instanceMethods.begin(); it != _instanceMethods.end(); it++) { MethodList methodList = it -> second; for (MethodList::iterator mit = methodList.begin(); mit != methodList.end(); mit++) { (*mit) -> release(); } } //释放属性 for (PropertyMap::iterator it = _properties.begin(); it != _properties.end(); it++) { it -> second -> release(); } }
bool RuntimeObjectImp::hasProperty(ExecState *exec, const Identifier &propertyName) const { bool result = false; instance->begin(); Field *aField = instance->getClass()->fieldNamed(propertyName.ascii(), instance); if (aField) { instance->end(); return true; } MethodList methodList = instance->getClass()->methodsNamed(propertyName.ascii(), instance); instance->end(); if (methodList.length() > 0) return true; return result; }
JSValuePtr JavaInstance::invokeMethod (ExecState *exec, const MethodList &methodList, const ArgList &args) { int i, count = args.size(); jvalue *jArgs; JSValuePtr resultValue; Method *method = 0; size_t numMethods = methodList.size(); // Try to find a good match for the overloaded method. The // fundamental problem is that JavaScript doesn have the // notion of method overloading and Java does. We could // get a bit more sophisticated and attempt to does some // type checking as we as checking the number of parameters. Method *aMethod; for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) { aMethod = methodList[methodIndex]; if (aMethod->numParameters() == count) { method = aMethod; break; } } if (method == 0) { JS_LOG ("unable to find an appropiate method\n"); return jsUndefined(); } const JavaMethod *jMethod = static_cast<const JavaMethod*>(method); JS_LOG ("call %s %s on %p\n", UString(jMethod->name()).UTF8String().c_str(), jMethod->signature(), _instance->_instance); if (count > 0) { jArgs = (jvalue *)malloc (count * sizeof(jvalue)); } else jArgs = 0; for (i = 0; i < count; i++) { JavaParameter* aParameter = jMethod->parameterAt(i); jArgs[i] = convertValueToJValue(exec, args.at(exec, i), aParameter->getJNIType(), aParameter->type()); JS_LOG("arg[%d] = %s\n", i, args.at(exec, i).toString(exec).ascii()); } jvalue result; // Try to use the JNI abstraction first, otherwise fall back to // nornmal JNI. The JNI dispatch abstraction allows the Java plugin // to dispatch the call on the appropriate internal VM thread. RootObject* rootObject = this->rootObject(); if (!rootObject) return jsUndefined(); bool handled = false; if (rootObject->nativeHandle()) { jobject obj = _instance->_instance; JSValuePtr exceptionDescription = noValue(); const char *callingURL = 0; // FIXME, need to propagate calling URL to Java handled = dispatchJNICall(exec, rootObject->nativeHandle(), obj, jMethod->isStatic(), jMethod->JNIReturnType(), jMethod->methodID(obj), jArgs, result, callingURL, exceptionDescription); if (exceptionDescription) { throwError(exec, GeneralError, exceptionDescription.toString(exec)); free (jArgs); return jsUndefined(); } } // The following code can be conditionally removed once we have a Tiger update that // contains the new Java plugin. It is needed for builds prior to Tiger. if (!handled) { jobject obj = _instance->_instance; switch (jMethod->JNIReturnType()){ case void_type: callJNIMethodIDA<void>(obj, jMethod->methodID(obj), jArgs); break; case object_type: result.l = callJNIMethodIDA<jobject>(obj, jMethod->methodID(obj), jArgs); break; case boolean_type: result.z = callJNIMethodIDA<jboolean>(obj, jMethod->methodID(obj), jArgs); break; case byte_type: result.b = callJNIMethodIDA<jbyte>(obj, jMethod->methodID(obj), jArgs); break; case char_type: result.c = callJNIMethodIDA<jchar>(obj, jMethod->methodID(obj), jArgs); break; case short_type: result.s = callJNIMethodIDA<jshort>(obj, jMethod->methodID(obj), jArgs); break; case int_type: result.i = callJNIMethodIDA<jint>(obj, jMethod->methodID(obj), jArgs); break; case long_type: result.j = callJNIMethodIDA<jlong>(obj, jMethod->methodID(obj), jArgs); break; case float_type: result.f = callJNIMethodIDA<jfloat>(obj, jMethod->methodID(obj), jArgs); break; case double_type: result.d = callJNIMethodIDA<jdouble>(obj, jMethod->methodID(obj), jArgs); break; case invalid_type: default: break; } } switch (jMethod->JNIReturnType()){ case void_type: { resultValue = jsUndefined(); } break; case object_type: { if (result.l != 0) { const char *arrayType = jMethod->returnType(); if (arrayType[0] == '[') { resultValue = JavaArray::convertJObjectToArray(exec, result.l, arrayType, rootObject); } else { resultValue = JavaInstance::create(result.l, rootObject)->createRuntimeObject(exec); } } else { resultValue = jsUndefined(); } } break; case boolean_type: { resultValue = jsBoolean(result.z); } break; case byte_type: { resultValue = jsNumber(exec, result.b); } break; case char_type: { resultValue = jsNumber(exec, result.c); } break; case short_type: { resultValue = jsNumber(exec, result.s); } break; case int_type: { resultValue = jsNumber(exec, result.i); } break; case long_type: { resultValue = jsNumber(exec, result.j); } break; case float_type: { resultValue = jsNumber(exec, result.f); } break; case double_type: { resultValue = jsNumber(exec, result.d); } break; case invalid_type: default: { resultValue = jsUndefined(); } break; } free (jArgs); return resultValue; }
bool JavaInstance::invokeMethod(const char* methodName, const NPVariant* args, uint32_t count, NPVariant* resultValue) { int i; jvalue *jArgs; JavaMethod *method = 0; VOID_TO_NPVARIANT(*resultValue); MethodList methodList = getClass()->methodsNamed(methodName); size_t numMethods = methodList.size(); // Try to find a good match for the overloaded method. The // fundamental problem is that JavaScript doesn have the // notion of method overloading and Java does. We could // get a bit more sophisticated and attempt to does some // type checking as we as checking the number of parameters. JavaMethod *aMethod; for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) { aMethod = methodList[methodIndex]; if (aMethod->numParameters() == count) { method = aMethod; break; } } if (method == 0) { LOGW("unable to find an appropiate method\n"); return false; } const JavaMethod *jMethod = static_cast<const JavaMethod*>(method); if (count > 0) { jArgs = (jvalue *)malloc (count * sizeof(jvalue)); } else jArgs = 0; for (i = 0; i < count; i++) { JavaParameter* aParameter = jMethod->parameterAt(i); jArgs[i] = convertNPVariantToJValue(args[i], aParameter->getJNIType(), aParameter->type()); } jvalue result; // The following code can be conditionally removed once we have a Tiger update that // contains the new Java plugin. It is needed for builds prior to Tiger. { jobject obj = getLocalRef(); switch (jMethod->JNIReturnType()){ case void_type: callJNIMethodIDA<void>(obj, jMethod->methodID(obj), jArgs); break; case object_type: result.l = callJNIMethodIDA<jobject>(obj, jMethod->methodID(obj), jArgs); break; case boolean_type: result.z = callJNIMethodIDA<jboolean>(obj, jMethod->methodID(obj), jArgs); break; case byte_type: result.b = callJNIMethodIDA<jbyte>(obj, jMethod->methodID(obj), jArgs); break; case char_type: result.c = callJNIMethodIDA<jchar>(obj, jMethod->methodID(obj), jArgs); break; case short_type: result.s = callJNIMethodIDA<jshort>(obj, jMethod->methodID(obj), jArgs); break; case int_type: result.i = callJNIMethodIDA<jint>(obj, jMethod->methodID(obj), jArgs); break; case long_type: result.j = callJNIMethodIDA<jlong>(obj, jMethod->methodID(obj), jArgs); break; case float_type: result.f = callJNIMethodIDA<jfloat>(obj, jMethod->methodID(obj), jArgs); break; case double_type: result.d = callJNIMethodIDA<jdouble>(obj, jMethod->methodID(obj), jArgs); break; case invalid_type: default: break; } getJNIEnv()->DeleteLocalRef(obj); } convertJValueToNPVariant(result, jMethod->JNIReturnType(), jMethod->returnType(), resultValue); free (jArgs); return true; }
LuaExportMethodDescriptor* LuaExportTypeDescriptor::filterMethod(std::string const& methodName, LuaArgumentList arguments, bool isStatic) { MethodList methodList; if (isStatic) { MethodMap::iterator mapIt = _classMethods.find(methodName); if (mapIt != _classMethods.end()) { methodList = mapIt -> second; } } else { MethodMap::iterator mapIt = _instanceMethods.find(methodName); if (mapIt != _instanceMethods.end()) { methodList = mapIt -> second; } } if (methodList.size() > 1) { LuaExportMethodDescriptor *targetMethod = NULL; int startIndex = isStatic ? 0 : 1; if (arguments.size() > startIndex) { //带参数 std::deque<std::string> signList; std::string signListStr; std::string signStrRegexp; for (LuaArgumentList::iterator it = arguments.begin() + startIndex; it != arguments.end(); it++) { LuaValue *value = *it; switch (value -> getType()) { case LuaValueTypeNumber: signList.push_back("N"); signListStr += "N"; signStrRegexp += "[fdcislqCISLQB@]"; break; case LuaValueTypeBoolean: signList.push_back("B"); signListStr += "B"; signStrRegexp += "[BcislqCISLQfd@]"; break; case LuaValueTypeInteger: signList.push_back("I"); signListStr += "I"; signStrRegexp += "[cislqCISLQfdB@]"; break; default: signList.push_back("O"); signListStr += "O"; signStrRegexp += "@"; break; } } std::string luaMethodSignStr = methodName + "_" + signListStr; MappingMethodMap::iterator methodIt = _methodsMapping.find(luaMethodSignStr); if (methodIt == _methodsMapping.end()) { //映射表无该方法,查找匹配方法 MethodList matchMethods; std::regex regExp(signStrRegexp); for (MethodList::iterator methodIt = methodList.begin(); methodIt != methodList.end(); methodIt ++) { LuaExportMethodDescriptor *methodDesc = *methodIt; if (std::regex_match(methodDesc -> methodSignature(), regExp)) { matchMethods.push_back(methodDesc); } } if (matchMethods.size() > 0) { //选择最匹配的方法 //备选方法,如果没有最匹配的情况下使用 LuaExportMethodDescriptor *alternateMethod = NULL; for (MethodList::iterator methodIt = matchMethods.begin(); methodIt != matchMethods.end(); methodIt ++) { LuaExportMethodDescriptor *methodDesc = *methodIt; bool hasMatch = true; bool hasAlternate = false; for (int i = 0; i < methodDesc -> methodSignature().length(); i++) { if (i < signList.size()) { std::string luaSign = signList[i]; char nativeSign = methodDesc -> methodSignature()[i]; if (luaSign == "N" && nativeSign != 'f' && nativeSign != 'd') { hasAlternate = true; luaSign = "I"; } if (luaSign == "B" && nativeSign != 'B') { hasMatch = false; break; } if (luaSign == "I" && nativeSign != 'c' && nativeSign != 'i' && nativeSign != 's' && nativeSign != 'l' && nativeSign != 'q' && nativeSign != 'C' && nativeSign != 'I' && nativeSign != 'S' && nativeSign != 'L' && nativeSign != 'Q') { hasMatch = false; break; } if (luaSign == "O" && nativeSign != '@') { hasMatch = false; break; } } } if (hasMatch) { if (hasAlternate) { //记录备选方法 alternateMethod = methodDesc; } else { //设置匹配方法 targetMethod = methodDesc; break; } } } if (targetMethod == NULL) { if (alternateMethod != NULL) { //使用备选方法 targetMethod = alternateMethod; } else { //没有最匹配则使用第一个方法 targetMethod = *(matchMethods.begin()); } } //设置方法映射 _methodsMapping[luaMethodSignStr] = targetMethod; } } else { targetMethod = methodIt -> second; } } else { //不带参数 for (MethodList::iterator it = methodList.begin(); it != methodList.end(); it++) { LuaExportMethodDescriptor *methodDesc = *it; if (methodDesc -> methodSignature() == "") { targetMethod = methodDesc; break; } } } return targetMethod; } else if (methodList.size() == 1) { return *(methodList.begin()); } return NULL; }