--
You received this message because you are subscribed to the Google Groups "RoboVM" group.
To unsubscribe from this group and stop receiving emails from it, send an email to robovm+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
I guess as long as Class.desiredAssertionStatus() returns only false, these assertions are not yet run.
cheers,
Simon
key steps to getting RoboVM in use as a library to sit behind a nice traditional Xcode-objc app.
I understand that its not Niklas' focus but its certainly not difficult and down the line it will make a great use case. In fact it is reasonably complex, if you are not comfortable configuring XCode to compile a slightly complex project, then this might be too much for you. I cannot offer support really if you have trouble with this process, but it would be nice to see other people being able to do the same thing.
Step 1- build your java library
--------------------------------------------------
- I code the main(String[] args) in Java. I think it is required. Example
class MyJavaRoboCode {
public static void main(String[] args) {
NSAutoreleasePool pool = new NSAutoreleasePool();
// initialize java objects, you can initialize native / JNI too
// here…
// …
// Then trigger my normal iOS app delegate
UIApplication.main(args, null, Delegate.class);
pool.drain();
}
// Corresponds to MyAppDelegate.m in my xcode project
@NativeClass("MyAppDelegate)
public static class Delegate extends UIApplicationDelegate.Adapter {
}
private static final native void nativeInit();
public static void callJava(String arg) {
System.out.println("Java was called from native with arg " + arg);
}
}
Step 2- Code the native side that you mix into your traditional nice XCode project.
--------------------------------------------------
- the native side of the JNI is written in a c++ file to be added to XCode
- we bridge to and from java here: brdige.cpp =
#include <stdio.h>
#include <string.h>
#include "robovm.h"
#include "robovm/exception.h"
#include "robovm/method.h"
extern "C" {
void Java_com_blah_JavaMain_nativeInit(Env* env, Class* c);
void Java_com_blah_JavaMain_nativeInit(Env* env, Class* c)
{
printf("In native\n");
JNIEnv* jniEnv = &(env->jni);
// Do things with jniEnv - e.g. lookup classIds and methodIds in java, and
// Save them to be used later. Or do whatever you want.
}
}
void callSomethingInJava(const char* arg)
{
// To call into java from your native app, use JNI
Env* rvmEnv = rvmGetEnv();
JNIEnv* jniEnv = &(rvmEnv->jni);
jclass myJavaClass = jniEnv->FindClass("com/mine/MyJavaRoboCode");
jMethodID myJavaMethod = jniEnv->GetStaticMethodID(myJavaClass, "callJava", "(Ljava/lang/String;)V");
jstring argAsJavaString = jniEnv->NewStringUTF(arg);
jniEnv->CallStaticVoidMethod(myJavaClass, myJavaMethod, argAsJavaString);
}
--------------------------------
The robovm headers necessary for compiling the JNI code are found in the RoboVM source repo:
vm/core/include
So add this to your xcode include paths.
I have found one header is missing and referenced from vm/core/include/robovm.h
gc.h is not found? (I havent looked into it, perhaps its just found in a different folder).
This header for the moment appears to not be required - I modified vm/core/include/robovm.h and removed the reference to it.
So, you have the native side, you have the java side, you need your nice normal XCode app to compile your JNI native code and of course link with the outputs of JVM. This can be done…
1. RoboVM must be set up normally, and your java code should be put into a normal RoboVM project as the main class. It should be compilable, but it wont run as it depending upon the XCode application for the main app delegate.
2. We run RoboVM from the command line so that we can parse its output. Make a script as follows:
arch_and_target_args="-arch x86"
exe_outdir=./temp_simu_exe
target_static_lib=./my_robo_simulator_lib.a
robovms_classpath=/opt/robovm/lib/robovm-objc.jar:/opt/robovm/lib/robovm-cocoatouch.jar
my_custom_classpath=bin
command="/opt/robovm/bin/robovm -verbose -properties robovm.properties -config robovm.xml ${arch_and_target_args} -d ${exe_outdir} -cp ${robovms_classpath}:${my_custom_classpath}"
echo Executing: $command
store_robo_compile_output=.last_robo_compile_output
# rm old output incase new call fails or screws up
rm -f $store_robo_compile_output
$command | tee $store_robo_compile_output
# The magic of SED gets us the OBJECT filelist, and also the exported symbol list, out of robovm's compile log
objectsListFile=$(cat $store_robo_compile_output | grep -- '-Wl,-filelist,' | sed -e 's/^.*-filelist,\([^ ]*\) .*/\1/')
exportedSymListFile=$(cat $store_robo_compile_output | grep -- '-exported_symbols_list' | sed -e 's/^.*-exported_symbols_list \([^ ]*\) .*/\1/')
# Those live right now in a temp directory, copy them locally
target_objects_file=$target_xcode_project_dir/compiled_simulator_objects.list
target_exp_symbols_file=$target_xcode_project_dir/exported_simulator_symbols.list
cp "$objectsListFile" "$target_objects_file"
cp "$exportedSymListFile" "$target_exp_symbols_file"
# Optional - we can archive the objects into a static library now, or tell XCode to use that object file list directly
libtool -static -o ${target_static_lib} -filelist ${target_objects_file}
3. If the script above is good, it will run robovm for us, and parse from the final step of RoboVM which is when it compiles the final app.
From there we just want the object files robovm has built, we take therefore the object_file_list from the output, and feed this later into XCode.
Optionally we can make a static lib from the object files with the libtool call.
The next step is to configure XCode to link in the RoboVM magic correctly.
Configuring XCode is always a lot of fun, the best way in my opinion is
- Add the compiled static library to the project (my_robo_simulator_lib.a)
- Set linker flags so XCode compiles the rest of the robovm runtime in. E.g. For targeting Simulator:
-L "$(ROBOVM_VM_DIR)/x86"
-Wl,-no_implicit_dylibs -Wl,-dead_strip -lrobovm-bc
-force_load "$(ROBOVM_VM_DIR)/x86/librobovm-rt.a"
-lrobovm-core -lgc -lpthread -ldl -lm -lstdc++ -liconv -lsqlite3
-exported_symbols_list exported_simulator_symbols.list
(These are flags copied from the output of RoboVM's normal compile. Be careful if you change them, you might break something)
(ROBOVM_VM_DIR is an Xcode env variable I set currently to /opt/local/robovm/lib/vm/ios)
4. Extra step - RoboVM collects your java resource files into jars which are placed in the output application,
in our case they should end be in temp_simu_exe/lib
- Add or copy or otherwise link this lib directory to your XCode project
5. Compile & Run in XCode! (Phew, was that worth it?)
- try adding breakpoints to your jni bridge code, see calls going into and out of the java.
- watch out for general JNI challenges - exceptions etc.
This is for iOS simulator, and so for the device build you need to obviously re run robovm with thumbv7 arch, consider sending output
to a different set of a files, different library etc. Dont forget the linker flags in XCode must match the device target, you can
fortunately tell XCode to use different linker flags for device vs simulator target… fun fun
--