Skip to content

Commit

Permalink
Merge pull request #3 from multi-os-engine-community/moe-master
Browse files Browse the repository at this point in the history
Merging from multi-os-engine-community
  • Loading branch information
Noisyfox authored May 5, 2021
2 parents 7b6118a + 7e9065b commit 0d387dd
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 40 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ local.properties
.project
.classpath
.settings
bin/
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ for (target in ['ios', 'macos', 'windows', 'ndk']) {

allprojects {
group 'org.moe'
version '1.1.3'
version '1.1.5'
}

/****************************
Expand Down
2 changes: 1 addition & 1 deletion natj-win/mingw.mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class timed_mutex: public _NonRecursiveMutex<recursive_timed_mutex>
public:
using base::base;
template <class Rep, class Period>
void try_lock_for(const std::chrono::duration<Rep,Period>& dur)
bool try_lock_for(const std::chrono::duration<Rep,Period>& dur)
{
bool ret = base::try_lock_for(dur);
#ifdef STDTHREAD_STRICT_NONRECURSIVE_LOCKS
Expand Down
68 changes: 68 additions & 0 deletions src/main/java/org/moe/natj/general/NatJ.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
Expand Down Expand Up @@ -919,6 +922,71 @@ public static class NativeObjectConstructionInfo {
public Mapper mapper;
}

public static Annotation[][] getParameterAnnotationsInherited(Method method) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 0) {
return new Annotation[0][];
}

List<List<Annotation>> results = new ArrayList<>(parameterTypes.length);
for (int i = 0; i < parameterTypes.length; i++) {
results.add(new ArrayList<Annotation>());
}

ArrayList<Class<?>> supers = new ArrayList<>();
// First get annotations from interfaces
Class<?> methodDeclaredKlass = method.getDeclaringClass();
Class<?>[] interfaces = methodDeclaredKlass.getInterfaces();
supers.addAll(Arrays.asList(interfaces));
// Then super class
Class<?> superClass = methodDeclaredKlass.getSuperclass();
if (superClass != null) {
supers.add(superClass);
}

for (Class<?> c : supers) {
// Find method
try {
for (Method sm : c.getDeclaredMethods()) {
int modifiers = sm.getModifiers();
if (Modifier.isStatic(modifiers)
|| Modifier.isPrivate(modifiers)
|| Modifier.isFinal(modifiers)) {
continue;
}

if (method.getName().equals(sm.getName()) && Arrays.equals(parameterTypes, sm.getParameterTypes())) {
int idx = 0;
for (Annotation[] annotations : sm.getParameterAnnotations()) {
results.get(idx).addAll(Arrays.asList(annotations));
idx++;
}
break;
}
}
} catch (Throwable e) {
// Do nothing
}
}

// Finally add annotations from current method
int idx = 0;
for (Annotation[] annotations : method.getParameterAnnotations()) {
results.get(idx).addAll(Arrays.asList(annotations));
idx++;
}

// Convert list to array
Annotation[][] resultArray = new Annotation[parameterTypes.length][];
for (int i = 0; i < parameterTypes.length; i++) {
List<Annotation> al = results.get(i);
Annotation[] aa = new Annotation[al.size()];
aa = al.toArray(aa);
resultArray[i] = aa;
}
return resultArray;
}

/**
* Constructs a {@link JavaObjectConstructionInfo} instance.
*
Expand Down
118 changes: 83 additions & 35 deletions src/main/java/org/moe/natj/objc/map/ObjCCallbackMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import org.moe.natj.general.NatJ;
import org.moe.natj.general.Pointer;
import org.moe.natj.general.ann.Runtime;
import org.moe.natj.objc.ObjCObject;
import org.moe.natj.objc.ObjCRuntime;
import org.moe.natj.objc.WeakReference;
import org.moe.natj.objc.ann.ObjCBlock;
Expand Down Expand Up @@ -126,30 +125,79 @@ public static Pointer createStrongBlockBindingPointer(long peer, boolean owned)

/**
* Base for invocation handlers.
*
* Handling of hashCode(), equals() and toString() use the sample code from
* https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html
*/
private abstract static class BlockInvocationHandler implements InvocationHandler {
// preloaded Method objects for the methods in java.lang.Object
private static Method hashCodeMethod;
private static Method equalsMethod;
private static Method toStringMethod;
static {
try {
hashCodeMethod = Object.class.getMethod("hashCode", null);
equalsMethod = Object.class.getMethod("equals", new Class[] { Object.class });
toStringMethod = Object.class.getMethod("toString", null);
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}

private final String name;
public Pointer peer;
public long data;

protected BlockInvocationHandler(Pointer peer, long data) {
protected BlockInvocationHandler(String name, Pointer peer, long data) {
this.name = name;
this.peer = peer;
this.data = data;
}

@Override
public abstract Object invoke(Object proxy, Method method, Object[] args);
public Object invoke(Object proxy, Method method, Object[] args) {
Class declaringClass = method.getDeclaringClass();

if (declaringClass == Object.class) {
if (method.equals(hashCodeMethod)) {
return proxyHashCode(proxy);
} else if (method.equals(equalsMethod)) {
return proxyEquals(proxy, args[0]);
} else if (method.equals(toStringMethod)) {
return proxyToString(proxy);
} else {
throw new InternalError("unexpected Object method dispatched: " + method);
}
} else {
return invoke0(proxy, method, args);
}
}

protected Integer proxyHashCode(Object proxy) {
return new Integer(System.identityHashCode(proxy));
}

protected Boolean proxyEquals(Object proxy, Object other) {
return (proxy == other ? Boolean.TRUE : Boolean.FALSE);
}

protected String proxyToString(Object proxy) {
return name + '@' + Integer.toHexString(proxy.hashCode());
}

protected abstract Object invoke0(Object proxy, Method method, Object[] args);
}

/**
* Invocation handler for native blocks with boolean return value.
*/
private static class BooleanInvocationHandler extends BlockInvocationHandler {
public BooleanInvocationHandler(Pointer peer, long data) {
super(peer, data);
public BooleanInvocationHandler(String name, Pointer peer, long data) {
super(name, peer, data);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke0(Object proxy, Method method, Object[] args) {
return new Boolean(ObjCRuntime.forwardBooleanBlockCall(peer.getPeer(), data, args));
}
}
Expand All @@ -158,12 +206,12 @@ public Object invoke(Object proxy, Method method, Object[] args) {
* Invocation handler for native blocks with byte return value.
*/
private static class ByteInvocationHandler extends BlockInvocationHandler {
public ByteInvocationHandler(Pointer peer, long data) {
super(peer, data);
public ByteInvocationHandler(String name, Pointer peer, long data) {
super(name, peer, data);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke0(Object proxy, Method method, Object[] args) {
return new Byte(ObjCRuntime.forwardByteBlockCall(peer.getPeer(), data, args));
}
}
Expand All @@ -172,12 +220,12 @@ public Object invoke(Object proxy, Method method, Object[] args) {
* Invocation handler for native blocks with char return value.
*/
private static class CharacterInvocationHandler extends BlockInvocationHandler {
public CharacterInvocationHandler(Pointer peer, long data) {
super(peer, data);
public CharacterInvocationHandler(String name, Pointer peer, long data) {
super(name, peer, data);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke0(Object proxy, Method method, Object[] args) {
return new Character(ObjCRuntime.forwardCharBlockCall(peer.getPeer(), data, args));
}
}
Expand All @@ -186,12 +234,12 @@ public Object invoke(Object proxy, Method method, Object[] args) {
* Invocation handler for native blocks with short return value.
*/
private static class ShortInvocationHandler extends BlockInvocationHandler {
public ShortInvocationHandler(Pointer peer, long data) {
super(peer, data);
public ShortInvocationHandler(String name, Pointer peer, long data) {
super(name, peer, data);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke0(Object proxy, Method method, Object[] args) {
return new Short(ObjCRuntime.forwardShortBlockCall(peer.getPeer(), data, args));
}
}
Expand All @@ -200,12 +248,12 @@ public Object invoke(Object proxy, Method method, Object[] args) {
* Invocation handler for native blocks with int return value.
*/
private static class IntegerInvocationHandler extends BlockInvocationHandler {
public IntegerInvocationHandler(Pointer peer, long data) {
super(peer, data);
public IntegerInvocationHandler(String name, Pointer peer, long data) {
super(name, peer, data);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke0(Object proxy, Method method, Object[] args) {
return new Integer(ObjCRuntime.forwardIntBlockCall(peer.getPeer(), data, args));
}
}
Expand All @@ -214,12 +262,12 @@ public Object invoke(Object proxy, Method method, Object[] args) {
* Invocation handler for native blocks with long return value.
*/
private static class LongInvocationHandler extends BlockInvocationHandler {
public LongInvocationHandler(Pointer peer, long data) {
super(peer, data);
public LongInvocationHandler(String name, Pointer peer, long data) {
super(name, peer, data);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke0(Object proxy, Method method, Object[] args) {
return new Long(ObjCRuntime.forwardLongBlockCall(peer.getPeer(), data, args));
}
}
Expand All @@ -228,12 +276,12 @@ public Object invoke(Object proxy, Method method, Object[] args) {
* Invocation handler for native blocks with float return value.
*/
private static class FloatInvocationHandler extends BlockInvocationHandler {
public FloatInvocationHandler(Pointer peer, long data) {
super(peer, data);
public FloatInvocationHandler(String name, Pointer peer, long data) {
super(name, peer, data);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke0(Object proxy, Method method, Object[] args) {
return new Float(ObjCRuntime.forwardFloatBlockCall(peer.getPeer(), data, args));
}
}
Expand All @@ -242,12 +290,12 @@ public Object invoke(Object proxy, Method method, Object[] args) {
* Invocation handler for native blocks with double return value.
*/
private static class DoubleInvocationHandler extends BlockInvocationHandler {
public DoubleInvocationHandler(Pointer peer, long data) {
super(peer, data);
public DoubleInvocationHandler(String name, Pointer peer, long data) {
super(name, peer, data);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke0(Object proxy, Method method, Object[] args) {
return new Double(ObjCRuntime.forwardDoubleBlockCall(peer.getPeer(), data, args));
}
}
Expand All @@ -256,12 +304,12 @@ public Object invoke(Object proxy, Method method, Object[] args) {
* Invocation handler for native blocks with boolean return value.
*/
private static class VoidInvocationHandler extends BlockInvocationHandler {
public VoidInvocationHandler(Pointer peer, long data) {
super(peer, data);
public VoidInvocationHandler(String name, Pointer peer, long data) {
super(name, peer, data);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke0(Object proxy, Method method, Object[] args) {
ObjCRuntime.forwardVoidBlockCall(peer.getPeer(), data, args);
return null;
}
Expand All @@ -271,12 +319,12 @@ public Object invoke(Object proxy, Method method, Object[] args) {
* Invocation handler for native blocks with boolean return value.
*/
private static class ObjectInvocationHandler extends BlockInvocationHandler {
public ObjectInvocationHandler(Pointer peer, long data) {
super(peer, data);
public ObjectInvocationHandler(String name, Pointer peer, long data) {
super(name, peer, data);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) {
public Object invoke0(Object proxy, Method method, Object[] args) {
return ObjCRuntime.forwardObjectBlockCall(peer.getPeer(), data, args);
}
}
Expand Down Expand Up @@ -571,7 +619,7 @@ private Object objectToJava(long peer, NatJ.JavaObjectConstructionInfo info) {
}
try {
blockInfo.handlerConstructor = handler.getConstructor(
Pointer.class, Long.TYPE);
String.class, Pointer.class, Long.TYPE);
blockInfo.proxyConstructor = Proxy.getProxyClass(
info.type.getClassLoader(), new Class[] {
info.type
Expand All @@ -592,7 +640,7 @@ private Object objectToJava(long peer, NatJ.JavaObjectConstructionInfo info) {
}
try {
instance = blockInfo.proxyConstructor.newInstance(blockInfo.handlerConstructor
.newInstance(pointer, blockInfo.data));
.newInstance(info.type.getName(), pointer, blockInfo.data));
} catch (Exception e) {
throw new RuntimeException("Java object construction error!", e);
}
Expand Down
8 changes: 6 additions & 2 deletions src/main/native/natj/NatJ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ jmethodID gBuildNativeObjectInfoStaticMethod = NULL;
jmethodID gGetMappedMethod = NULL;
jmethodID gGetMappedReturnMethod = NULL;
jmethodID gGetParameterAnnotationsMethod = NULL;
jmethodID gGetParameterAnnotationsInheritedStaticMethod = NULL;
jmethodID gGetRuntimeStaticMethod = NULL;
jmethodID gGetNativeExceptionMethod = NULL;
jmethodID gGetMessageMethod = NULL;
Expand Down Expand Up @@ -403,6 +404,9 @@ void JNICALL Java_org_moe_natj_general_NatJ_initialize(JNIEnv* env, jclass clazz
gGetParameterAnnotationsMethod =
env->GetMethodID(gMethodClass, "getParameterAnnotations",
"()[[Ljava/lang/annotation/Annotation;");
gGetParameterAnnotationsInheritedStaticMethod =
env->GetStaticMethodID(gNatJClass, "getParameterAnnotationsInherited",
"(Ljava/lang/reflect/Method;)[[Ljava/lang/annotation/Annotation;");
gGetRuntimeStaticMethod = env->GetStaticMethodID(
gNatJClass, "getRuntime",
"(Ljava/lang/Class;Z)Lorg/moe/natj/general/NativeRuntime;");
Expand Down Expand Up @@ -866,8 +870,8 @@ void buildInfos(JNIEnv* env, jobject method, bool toJava, jobject** paramInfos,
#endif
jobjectArray parameterTypes =
(jobjectArray)env->CallObjectMethod(method, gGetParameterTypesMethod);
jobjectArray parameterAnns = (jobjectArray)env->CallObjectMethod(
method, gGetParameterAnnotationsMethod);
jobjectArray parameterAnns = (jobjectArray)env->CallStaticObjectMethod(
gNatJClass, gGetParameterAnnotationsInheritedStaticMethod, method);
jsize parameterCount = env->GetArrayLength(parameterTypes);
if (isVariadic) {
parameterCount--;
Expand Down
Loading

0 comments on commit 0d387dd

Please sign in to comment.