int main(int argc, char **args) { JX_Initialize(args[0], callback); JX_InitializeNewEngine(); JX_DefineMainFile(contents); JX_DefineExtension("sampleMethod", sampleMethod); JX_StartEngine(); while (JX_LoopOnce() != 0) usleep(1); JXValue *params[2] = {param1, param2}; JXValue out; // call fnc -> JS side function // we had made this variable persistent inside sampleMethod JX_CallFunction(fnc, *params, 2, &out); // we need to clear persistent and then free whenever we // are done with persistent values to not to leak JX_ClearPersistent(fnc); JX_Free(fnc); JX_ClearPersistent(param1); JX_Free(param1); JX_ClearPersistent(param2); JX_Free(param2); assert(JX_GetDataLength(&out) == 11 && "Expected return value was 'test{\"a\":3}"); JX_Free(&out); assert(out.data_ == NULL && out.size_ == 0 && "JX_FreeResultData leaks?"); JX_StopEngine(); }
// native sampleMethod void sampleMethod(JXValue *results, int argc) { for (int i = 0; i < argc; i++) { std::string str; ConvertResult(&results[i], str); if (compare_base[i] != str.c_str()[0]) { flush_console("FAIL! Item(%d) : %s \n", i, str.c_str()); exit(-1); } } JXValue out; // fnc represents the JS side function fnc = &results[9]; param1 = results + 3; param2 = results + 4; // call JS side fnc with 2 parameters and get // the result to 'out' JX_CallFunction(fnc, (results + 3), 2, &out); // make fnc persistent so we can call it later again // see 'int main' for second call JX_MakePersistent(fnc); JX_MakePersistent(param1); JX_MakePersistent(param2); assert(JX_GetDataLength(&out) == 11 && "Expected return value was 'test{\"a\":3}"); JX_Free(&out); assert(out.data_ == NULL && out.size_ == 0 && "JX_FreeResultData leaks?"); }
JNIEXPORT jbyteArray JNICALL Java_io_jxcore_node_jxcore_getBuffer(JNIEnv *env, jobject thiz, jlong id) { JXValue *val; if (id < 0) val = cb_values + (id + 3); else val = JX_RemoveStoredValue(0, id); char *arr = JX_GetString(val); int length = JX_GetDataLength(val); jbyteArray ret = env->NewByteArray(length); env->SetByteArrayRegion(ret, 0, length, (jbyte *)arr); free(arr); if (id >= 0) JX_Free(val); return ret; }
void sampleMethod(JXValue *results, int argc) { for (int i = 0; i < argc; i++) { std::string str; ConvertResult(&results[i], str); if (compare_base[i] != str.c_str()[0]) { flush_console("FAIL! Item(%d) : %s \n", i, str.c_str()); exit(-1); } } JXValue out; JX_CallFunction(&results[9], (results + 3), 2, &out); assert(JX_GetDataLength(&out) == 11 && "Expected return value was 'test{\"a\":3}"); JX_Free(&out); assert(out.data_ == NULL && out.size_ == 0 && "JX_FreeResultData leaks?"); }
static void callJXcoreNative(JXValue *results, int argc) { JNIEnv *env = jxcore::JniHelper::getEnv(); jclass arrClass = env->FindClass("java/util/ArrayList"); jmethodID arrInit = env->GetMethodID(arrClass, "<init>", "()V"); jobject objArray = env->NewObject(arrClass, arrInit); jmethodID addObject = env->GetMethodID(arrClass, "add", "(Ljava/lang/Object;)Z"); jclass boolClass = NULL; jmethodID boolMethod; jclass intClass = NULL; jmethodID intMethod; jclass doubleClass = NULL; jmethodID doubleMethod; jclass strClass = env->FindClass("java/lang/String"); for (int i = 0; i < argc; i++) { JXValue *result = results + i; jobject objValue = NULL; switch (result->type_) { case RT_Boolean: { if (boolClass == NULL) { boolClass = env->FindClass("java/lang/Boolean"); boolMethod = env->GetMethodID(boolClass, "<init>", "(Z)V"); } jboolean bl = JX_GetBoolean(result) ? JNI_TRUE : JNI_FALSE; objValue = env->NewObject(boolClass, boolMethod, bl); } break; case RT_Int32: { if (intClass == NULL) { intClass = env->FindClass("java/lang/Integer"); intMethod = env->GetMethodID(intClass, "<init>", "(I)V"); } jint nt = JX_GetInt32(result); objValue = env->NewObject(intClass, intMethod, nt); } break; case RT_Double: { if (doubleClass == NULL) { doubleClass = env->FindClass("java/lang/Double"); doubleMethod = env->GetMethodID(doubleClass, "<init>", "(D)V"); } jdouble db = JX_GetDouble(result); objValue = env->NewObject(doubleClass, doubleMethod, db); } break; case RT_Buffer: { char *arr = JX_GetString(result); int length = JX_GetDataLength(result); jbyteArray ret = env->NewByteArray(length); env->SetByteArrayRegion(ret, 0, length, (jbyte *)arr); objValue = (jobject)ret; free(arr); } break; case RT_Object: { std::string str_result; ConvertResult(result, str_result); const char *data = str_result.c_str(); int ln = JX_GetDataLength(result); if (ln > 0 && *data != '{' && *data != '[') { objValue = (jobject)env->NewStringUTF(str_result.c_str()); } else { jobjectArray ret = (jobjectArray)env->NewObjectArray( 1, strClass, env->NewStringUTF("")); jstring jstr = env->NewStringUTF(str_result.c_str()); env->SetObjectArrayElement(ret, 0, jstr); objValue = (jobject)ret; env->DeleteLocalRef(jstr); } } break; case RT_Error: case RT_String: { std::string str_result; ConvertResult(result, str_result); objValue = env->NewStringUTF(str_result.c_str()); } break; default: break; } env->CallBooleanMethod(objArray, addObject, objValue); env->DeleteLocalRef(objValue); } jxcore::CallJava(objArray); env->DeleteLocalRef(objArray); env->DeleteLocalRef(arrClass); env->DeleteLocalRef(strClass); if (doubleClass != NULL) env->DeleteLocalRef(doubleClass); if (intClass != NULL) env->DeleteLocalRef(intClass); if (boolClass != NULL) env->DeleteLocalRef(boolClass); }