@yglukhov: Now that I'm stuck at home and have lots of time to work on this, 
I've made it work as follows:

Most of the things that made it not work before were things not complete in 
other examples such as @akavel's "hellomello" or @treeform's [GLFM 
project](https://forum.nim-lang.org/t/5197#32584) with people not really 
understanding the relationship between the Android GC and Nim's, with many 
recommending not using Nim's GC but using \--gc:none or one of the new 
experimental ones; doing that isn't really satisfactory as one then can't 
easily use Nim's strings (or any other structure that uses heap data) and needs 
to do a lot of work generating cstrings themselves and manually memory managing 
them to avoid memory leaks.

In fact, the official Nim documentation contains most of what is needed, with 
@araq seeming have worked on this at one time, as follows:

  1. The need to call NimMain() before doing anything else is documented 
[here](https://nim-lang.org/docs/nimc.html#cross-compilation-for-android). I 
think the very slickest way to do this for a dynamically loaded library is to 
use the JNI_OnLoad event so that is what I've done and will continue to do.
  2. The above link recommends using Nim as compile-only to generated the 
required C or C++ files implying that one then uses the Android Studio Gradle 
build scripts to do the rest, but that second step means we need to make 
"nimbase.h" available to Gradle to find, which is mentioned 
[here](https://nim-lang.org/docs/backends.html#backend-code-calling-nim-nim-invocation-example-from-c).



There are things that I haven't seen mentioned anywhere as follows:

  1. Gradle is usually used to produce different "flavors" of the required 
APK/Bundle files containing APK's for the different supported ANDROID_ABI's 
(armeabi-v7a, arm64v8a and x86, and x86_64 currently) ans well as a "fat" APK 
containing all of them from which the Android installation system can select 
the native libraries required. That is easy for C/C++ where primitive types 
always have the same number of bits no matter the platform, but Nim has 
different int/uint bitedness depending on the platform and thus we need 
separate compilations for each CPU. I chose to use ndk-build Android.mk make 
files (I find them simplere to use) and adjusted them to account for the (four) 
different directories that must be used to cover this case.
  2. The above mentioned Android.mk file needs to be adjusted to refer to 
LOCAL_LIBS in order to add other Android capabilities such as logging.
  3. Theoretically, one could refer to the required "nimbase.h" file in place 
from the "Android.mk" file so one wouldn't need to make a copy into the code 
base, but I couldn't get that working nor did I see any forum posts where 
anyone has. If anyone can solve this, it would be appreciated!



In my projects, I have included a copy of @yglukhov's jnim "jni_wrapper.nim" 
file as a convenient way to use all the boilerplate, and have tried to include 
all due licence conformity.

So my first working project was to translate Android's NDK sample "hello-jni" 
from C to Nim, which is successful as per my repo 
<https://github.com/GordonBGood/NimHelloJNI>'. This example is similar to 
@akavel's "hellomello" project but doesn't depend on `NativeActivity, needs 
Android Studio (and its contained JDK) in order to be used, but is more 
complete due to the above reasons.

My second and more useful example was to translate Android's NDK sample 
"hello-jnicallback" from C to Nim, which is successful as per my [repo 
<https://github.com/GordonBGood/NimHelloJNICallback>'; this includes all of the 
above but shows how to move data back and forth between native Nim and the 
Android Java/Kotlin code via called methods and includes a background thread as 
@glukhov mentioned using in one of the posts 
`above](https://forum.nim-lang.org/t/6045#37435).

So I'm finally ready to write my Android benchmark app using what I have 
learned so far, and will post a link to the repo and comment on its development 
here when it is up and running, which I no longer have any doubts about being 
able to do. Although I have the Nim GC running, my actual multi-threaded code 
won't be using heap data to avoid the problems and overhead of multiple heap 
spaces, thus I will give up on the use of channels and threadpools which I 
don't regard as being stable enough for use until they are stable for use with 
the new -gc:arc; that would make the code more elegant but won't make any 
difference to the speed of the benchmark.

So, to get on with it...

Reply via email to