Skip to content

Commit d022b46

Browse files
committed
[[ ExternalsApiV5 ]] Reworked java_lcapi_LCCreateArguments to use pre-initialised class/method names.
[[ ExternalsApiV5 ]] Added support for cdata mapping to java LCCreateArguments (can either be ByteBuffer, or byte[]).
1 parent 64b9206 commit d022b46

3 files changed

Lines changed: 154 additions & 136 deletions

File tree

lcidlc/src/InterfaceGenerate.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,6 +1532,10 @@ bool DLLEXPORT MCExternalInitialize(MCExternalInterface *p_interface)\n\
15321532
\n\
15331533
s_interface -> interface_query(kMCExternalInterfaceQueryScriptJavaEnv, &s_engine_env);\n\
15341534
s_interface -> interface_query(kMCExternalInterfaceQuerySystemJavaEnv, &s_android_env);\n\
1535+
\n\
1536+
if (!java__initialize(s_engine_env))\n\
1537+
return false;\n\
1538+
\n\
15351539
#endif\n\
15361540
\n\
15371541
#ifdef kMCExternalStartup\n\
@@ -1547,6 +1551,11 @@ void DLLEXPORT MCExternalFinalize(void)\n\
15471551
#ifdef kMCExternalShutdown\n\
15481552
kMCExternalShutdown();\n\
15491553
#endif\n\
1554+
\n\
1555+
#ifdef __ANDROID__\n\
1556+
java__finalize(s_engine_env);\n\
1557+
#endif\n\
1558+
\n\
15501559
}\n\n\
15511560
";
15521561

lcidlc/src/Support.mm

Lines changed: 137 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -2828,6 +2828,69 @@ static bool verify__out_parameter(const char *arg, MCVariableRef var)
28282828

28292829
//////////
28302830

2831+
enum JavaNativeType
2832+
{
2833+
kJavaNativeTypeBoolean,
2834+
kJavaNativeTypeInteger,
2835+
kJavaNativeTypeDouble,
2836+
kJavaNativeTypeString,
2837+
kJavaNativeTypeData,
2838+
};
2839+
2840+
struct JavaNativeMapping
2841+
{
2842+
JavaNativeType type;
2843+
const char *class_name;
2844+
const char *method_name;
2845+
const char *method_sig;
2846+
jclass java_class;
2847+
jmethodID java_method;
2848+
};
2849+
2850+
static JavaNativeMapping s_native_mappings[] =
2851+
{
2852+
{ kJavaNativeTypeBoolean, "java/lang/Boolean", "booleanValue", "()Z", nil, nil },
2853+
{ kJavaNativeTypeInteger, "java/lang/Integer", "intValue", "()I", nil, nil },
2854+
{ kJavaNativeTypeDouble, "java/lang/Double", "doubleValue", "()D", nil, nil },
2855+
{ kJavaNativeTypeString, "java/lang/String", nil, nil, nil, nil },
2856+
{ kJavaNativeTypeData, "[B", nil, nil, nil, nil },
2857+
{ kJavaNativeTypeData, "java/nio/ByteBuffer", "array", "()[B", nil, nil },
2858+
};
2859+
2860+
static bool java__initialize(JNIEnv *env)
2861+
{
2862+
for(uint32_t i = 0; i < sizeof(s_native_mappings) / sizeof(s_native_mappings[0]); i++)
2863+
{
2864+
jclass t_class;
2865+
t_class = env -> FindClass(s_native_mappings[i] . class_name);
2866+
if (t_class == nil)
2867+
return false;
2868+
2869+
s_native_mappings[i] . java_class = (jclass)env -> NewGlobalRef(t_class);
2870+
if (s_native_mappings[i] . java_class == nil)
2871+
return false;
2872+
2873+
if (s_native_mappings[i] . method_name != nil)
2874+
{
2875+
s_native_mappings[i] . java_method = env -> GetMethodID(t_class, s_native_mappings[i] . method_name, s_native_mappings[i] . method_sig);
2876+
if (s_native_mappings[i] . java_method == nil)
2877+
return false;
2878+
}
2879+
else
2880+
s_native_mappings[i] . java_method = nil;
2881+
}
2882+
2883+
return true;
2884+
}
2885+
2886+
static void java__finalize(JNIEnv *env)
2887+
{
2888+
for(uint32_t i = 0; i < sizeof(s_native_mappings) / sizeof(s_native_mappings[0]); i++)
2889+
env -> DeleteGlobalRef(s_native_mappings[i] . java_class);
2890+
}
2891+
2892+
//////////
2893+
28312894
static jobject java__get_activity(void)
28322895
{
28332896
jobject t_activity;
@@ -3050,7 +3113,7 @@ static void free__java_data(JNIEnv *env, jobject value)
30503113
}
30513114

30523115
//////////
3053-
3116+
30543117
static void java_lcapi__throw(JNIEnv *env, LCError p_error)
30553118
{
30563119
// TODO
@@ -3115,7 +3178,7 @@ static jboolean java_lcapi_ObjectExists(JNIEnv *env, jlong object)
31153178
}
31163179

31173180
static LCError java_lcapi_LCCreateArguments(JNIEnv *env, jobjectArray arguments, MCVariableRef*& r_argv, uint32_t& r_argc)
3118-
{
3181+
{
31193182
LCError t_error;
31203183
t_error = kLCErrorNone;
31213184

@@ -3131,150 +3194,90 @@ static LCError java_lcapi_LCCreateArguments(JNIEnv *env, jobjectArray arguments,
31313194
if (t_argv == nil)
31323195
return kLCErrorOutOfMemory;
31333196
}
3134-
3135-
// Get all the classes we want to support
3136-
3137-
jclass t_class_String;
3138-
3139-
if (t_error == kLCErrorNone)
3140-
{
3141-
t_class_String = nil;
3142-
t_class_String = env->FindClass("java/lang/String");
3143-
if (t_class_String == nil)
3144-
t_error = kLCErrorFailed;
3145-
}
31463197

3147-
jclass t_class_Boolean;
3148-
3149-
if (t_error == kLCErrorNone)
3150-
{
3151-
t_class_Boolean = nil;
3152-
t_class_Boolean = env->FindClass("java/lang/Boolean");
3153-
if (t_class_Boolean == nil)
3154-
t_error = kLCErrorFailed;
3155-
}
3156-
3157-
jclass t_class_Integer;
3158-
3159-
if (t_error == kLCErrorNone)
3160-
{
3161-
t_class_Integer = nil;
3162-
t_class_Integer = env->FindClass("java/lang/Integer");
3163-
if (t_class_Integer == nil)
3164-
t_error = kLCErrorFailed;
3165-
}
3166-
3167-
jclass t_class_Double;
3168-
3169-
if (t_error == kLCErrorNone)
3170-
{
3171-
t_class_Double = nil;
3172-
t_class_Double = env->FindClass("java/lang/Double");
3173-
if (t_class_Double == nil)
3174-
t_error = kLCErrorFailed;
3175-
}
3176-
3177-
jclass t_class_ByteBuffer;
3178-
3179-
if (t_error == kLCErrorNone)
3180-
{
3181-
t_class_ByteBuffer = nil;
3182-
t_class_ByteBuffer = env->FindClass("java/nio/ByteBuffer");
3183-
if (t_class_ByteBuffer == nil)
3184-
t_error = kLCErrorFailed;
3185-
}
3186-
3187-
// Get all the required methods so we don't need to get them multiple times
3188-
3189-
jmethodID t_mid_Boolean_booleanValue;
3190-
3191-
if (t_error == kLCErrorNone)
3192-
{
3193-
t_mid_Boolean_booleanValue = nil;
3194-
t_mid_Boolean_booleanValue = env->GetMethodID(t_class_Boolean, "booleanValue", "()Z");
3195-
if (t_mid_Boolean_booleanValue == nil)
3196-
t_error = kLCErrorFailed;
3197-
}
3198-
3199-
jmethodID t_mid_Integer_integerValue;
3200-
3201-
if (t_error == kLCErrorNone)
3202-
{
3203-
t_mid_Integer_integerValue = nil;
3204-
t_mid_Integer_integerValue = env->GetMethodID(t_class_Integer, "intValue", "()I");
3205-
if (t_mid_Integer_integerValue == nil)
3206-
t_error = kLCErrorFailed;
3207-
}
3208-
3209-
jmethodID t_mid_Double_doubleValue;
3210-
3211-
if (t_error == kLCErrorNone)
3212-
{
3213-
t_mid_Double_doubleValue = nil;
3214-
t_mid_Double_doubleValue = env->GetMethodID(t_class_Double, "doubleValue", "()D");
3215-
if (t_mid_Double_doubleValue == nil)
3216-
t_error = kLCErrorFailed;
3217-
}
3218-
3219-
jmethodID t_mid_ByteBuffer_array;
3220-
3221-
if (t_error == kLCErrorNone)
3222-
{
3223-
t_mid_ByteBuffer_array = nil;
3224-
t_mid_ByteBuffer_array = env->GetMethodID(t_class_ByteBuffer, "array", "()[B");
3225-
if (t_mid_ByteBuffer_array == nil)
3226-
t_error = kLCErrorFailed;
3227-
}
3228-
32293198
for (uint32_t i = 0; i < t_argc; i++)
32303199
{
3231-
t_error = (LCError)MCVariableCreate(&t_argv[i]);
3232-
if (t_error != kLCErrorNone)
3233-
break;
3200+
if (t_error == kLCErrorNone)
3201+
t_error = (LCError)MCVariableCreate(&t_argv[i]);
32343202

32353203
jobject t_param;
3236-
if (t_error == kLCErrorNone)
3204+
t_param = nil;
3205+
if (t_error == kLCErrorNone)
32373206
{
3238-
t_param = nil;
3239-
t_param = env->GetObjectArrayElement(arguments,i);
3207+
t_param = env->GetObjectArrayElement(arguments, i);
32403208
if (t_param == nil)
32413209
t_error = kLCErrorFailed;
32423210
}
32433211

32443212
if (t_error == kLCErrorNone)
32453213
{
3246-
// Compare to classes we know we can use
3247-
if (env->IsInstanceOf(t_param, t_class_String) == JNI_TRUE)
3248-
{
3249-
char *t_cstring;
3250-
t_error = java_to__cstring(env, t_param, t_cstring);
3251-
if (t_error == kLCErrorNone)
3252-
{
3253-
t_error = (LCError)MCVariableStore(t_argv[i], kMCOptionAsCString, &t_cstring);
3254-
free(t_cstring);
3255-
}
3256-
}
3257-
if (env->IsInstanceOf(t_param, t_class_Boolean) == JNI_TRUE)
3258-
{
3259-
bool t_boolean = (bool) env -> CallBooleanMethod(t_param,t_mid_Boolean_booleanValue);
3260-
t_error = (LCError)MCVariableStore(t_argv[i], kMCOptionAsBoolean, &t_boolean);
3261-
}
3262-
if (env->IsInstanceOf(t_param, t_class_Integer) == JNI_TRUE)
3263-
{
3264-
int t_integer = (int) env -> CallIntMethod(t_param,t_mid_Integer_integerValue);
3265-
t_error = (LCError)MCVariableStore(t_argv[i], kMCOptionAsInteger, &t_integer);
3266-
}
3267-
if (env->IsInstanceOf(t_param, t_class_Double) == JNI_TRUE)
3268-
{
3269-
double t_double = (double) env -> CallDoubleMethod(t_param,t_mid_Double_doubleValue);
3270-
t_error = (LCError)MCVariableStore(t_argv[i], kMCOptionAsReal, &t_double);
3271-
}
3272-
if (env->IsInstanceOf(t_param, t_class_ByteBuffer) == JNI_TRUE)
3273-
{
3274-
//jobject t_byte_array = env -> CallObjectMethod(t_param,t_mid_ByteBuffer_array);
3275-
//LCBytes t_bytes = java_to__cdata(env, t_byte_array);
3276-
//t_error = (LCError)MCVariableStore(t_argv[i], kMCOptionAsString, &t_bytes);
3277-
}
3214+
for(uint32_t j = 0; j < sizeof(s_native_mappings) / sizeof(s_native_mappings[0]); j++)
3215+
{
3216+
if (!env -> IsInstanceOf(t_param, s_native_mappings[j] . java_class) == JNI_TRUE)
3217+
continue;
3218+
3219+
JavaNativeMapping *t_mapping;
3220+
t_mapping = &s_native_mappings[j];
3221+
switch(t_mapping -> type)
3222+
{
3223+
case kJavaNativeTypeBoolean:
3224+
{
3225+
bool t_boolean;
3226+
t_boolean = (bool)env -> CallBooleanMethod(t_param, t_mapping -> java_method);
3227+
t_error = LCValueStore(t_argv[i], kLCValueOptionAsBoolean, &t_boolean);
3228+
}
3229+
break;
3230+
case kJavaNativeTypeInteger:
3231+
{
3232+
int t_integer;
3233+
t_integer = (bool)env -> CallIntMethod(t_param, t_mapping -> java_method);
3234+
t_error = LCValueStore(t_argv[i], kLCValueOptionAsInteger, &t_integer);
3235+
}
3236+
break;
3237+
case kJavaNativeTypeDouble:
3238+
{
3239+
double t_double;
3240+
t_double = (bool)env -> CallDoubleMethod(t_param, t_mapping -> java_method);
3241+
t_error = LCValueStore(t_argv[i], kLCValueOptionAsReal, &t_double);
3242+
}
3243+
break;
3244+
case kJavaNativeTypeString:
3245+
{
3246+
jobject t_java_string;
3247+
if (t_mapping -> java_method != nil)
3248+
t_java_string = (jobject)env -> CallObjectMethod(t_param, t_mapping -> java_method);
3249+
else
3250+
t_java_string = t_param;
3251+
3252+
char *t_cstring;
3253+
t_cstring = nil;
3254+
if (t_error == kLCErrorNone)
3255+
t_error = java_to__cstring(env, t_java_string, t_cstring);
3256+
if (t_error == kLCErrorNone)
3257+
t_error = LCValueStore(t_argv[i], kLCValueOptionAsCString, &t_cstring);
3258+
free(t_cstring);
3259+
}
3260+
break;
3261+
case kJavaNativeTypeData:
3262+
{
3263+
jobject t_java_data;
3264+
if (t_mapping -> java_method != nil)
3265+
t_java_data = (jobject)env -> CallObjectMethod(t_param, t_mapping -> java_method);
3266+
else
3267+
t_java_data = t_param;
3268+
3269+
LCBytes t_cdata;
3270+
if (t_error == kLCErrorNone)
3271+
{
3272+
t_cdata . buffer = env -> GetByteArrayElements((jbyteArray)t_java_data, nil);
3273+
t_cdata . length = env -> GetArrayLength((jbyteArray)t_java_data);
3274+
t_error = LCValueStore(t_argv[i], kLCValueOptionAsCData, &t_cdata);
3275+
env -> ReleaseByteArrayElements((jbyteArray)t_java_data, (jbyte *)t_cdata . buffer, 0);
3276+
}
3277+
}
3278+
break;
3279+
}
3280+
}
32783281
}
32793282
}
32803283

revtestexternal/src/revtestexternal.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,13 @@ public static void revTestExternalObjectPostAndSend()
112112
LC.Object t_target;
113113
t_target = LC.ContextMe();
114114

115-
t_target . Post("handlePost", 1, 1.0, false, "foobar");
116-
t_target . Send("handleSend", 1, 1.0, false, "foobar");
115+
try
116+
{
117+
t_target . Post("handlePost", 1, 1.0, false, "foobar", "foobaz" . getBytes("UTF-8"));
118+
t_target . Send("handleSend", 1, 1.0, false, "foobar", "foobaz" . getBytes("UTF-8"));
119+
}
120+
catch(Exception e)
121+
{
122+
}
117123
}
118124
};

0 commit comments

Comments
 (0)