discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Android app using GNUstep


From: Frederik Seiffert
Subject: Re: Android app using GNUstep
Date: Tue, 13 Oct 2020 12:18:47 +0200

Congrats on your launch!

Thanks Ivan!

Do you have an opensourced example for using the Java-ObjC bridge?

Not at the moment, but here’s the method for registering ObjC blocks as native JNI callbacks via MABlockClosure if that helps:

- (void)registerCallback:(NSString *)javaMethodName withSignature:(NSString *)signature usingHandler:(id)handler
{
MABlockClosure *blockClosure = [[MABlockClosure alloc] initWithBlock:[handler copy]];


JNINativeMethod nativeMethod = {
.name = javaMethodName.UTF8String,
.signature = signature.UTF8String,
.fnPtr = blockClosure.fptr
};


QAndroidJniEnvironment env;
env->RegisterNatives(self.jcls, &nativeMethod, 1);


if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
env->FatalError([NSString stringWithFormat:@"%@: failed to register bridge callback for '%@' with signature '%@'"self, javaMethodName, signature].UTF8String);
}


if (!self.blockClosures) {
self.blockClosures = [[NSMutableDictionary alloc] init];
}
self.blockClosures[javaMethodName] = blockClosure;
}


In order to associate Java objects with ObjC objects, we add a "private long objcObject" field to the Java object to store the pointer to the ObjC object. We can then read that field in the JNI callback in order to get the ObjC object that should handle the callback. When initializing Java objects from ObjC via JNI, we first allocate the object via AllocObject(), then call SetLongField() to set the objcObject field, and only then call the object’s init method. That way any native callbacks will also work during init. It’s all not very pretty but works well as long as you carefully manage the lifetimes of the ObjC and Java objects...

Hope that helps and let me know if I can provide any further details!

Frederik


Am 12.10.2020 um 14:47 schrieb Ivan Vučica <ivan@vucica.net>:

Congrats on your launch!

Looking forward to trying out the toolchain scripts. From following the patches here-and-there, this is bound to be much better than the hack I initially put together. I'm looking forward to rebuilding my old experimental code with the new process.

Do you have an opensourced example for using the Java-ObjC bridge?

On Mon, Oct 12, 2020 at 1:35 PM Frederik Seiffert <frederik@algoriddim.com> wrote:
Hi all,

I’m happy to share that we launched our app "djay" on Android using GNUstep:
https://play.google.com/store/apps/details?id=com.algoriddim.djay_free

It’s using the Android toolchain scripts to cross-compile GNUstep and its dependencies for Android:
https://github.com/gnustep/tools-android

The basic setup is Clang with libobjc2 using the 2.0 runtime, GNUstep-Base and libdispatch. Those components allow us to compile and run essentially all of our existing non-UI / non-platform specific code for Android without changes, which is multiple 100k LOC using ARC, on 4 ABIs (armeabi-v7a, arm64-v8a, x86, x86_64). I’m still amazed how well it all works.

For the UI we went with Qt/QML, which turned out to be a great fit. Like ObjC, Qt/QML is very dynamic at runtime, which enabled us to write some glue code that lets us do two-way bindings between QML UI components and our ObjC model using KVO/KVC. As the app is driven by Qt’s run loop, we’re driving NSRunLoop and libdispatch from Qt, which is currently done by swizzling NSRunLoop on launch.

We also wrote a Java-ObjC bridge that allows us to register ObjC blocks as native callbacks from Java (using libffi via Mike Ash’s MABlockClosure). It e.g. allows us to hook into the Android notification system and call ObjC methods when the user triggers playback controls on the home screen.

It’s been a challenging but very rewarding project, and it’s also been great to see how it improved our shared code base by forcing us to more strictly separate platform-specific code. I’m also happy that we could make some contributions to the GNUstep code base ourselves (67 PRs and counting ;)).

But most importantly we really could not have done it without the incredible work and support from the GNUstep community, including Greg, David, Fred, Richard, Niels, Ivan, and others. Thank you all for your help!

Frederik




reply via email to

[Prev in Thread] Current Thread [Next in Thread]