www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Interfacing via Java Native Interface

reply "Andrew" <diehertz gmail.com> writes:
Hello there!
I've decided to learn a bit of D, as I am currently Android 
Developer (mostly C++ <- JNI -> Java), I'm trying to create a D 
shared library which exports function (with extern (C)) for 
invocation from Java.
My .d file contains only a single function returning an int, 
.java calls this function several times.
This approach only works if d-function is trivial, e.g. it's not 
using any D functionality (I believe that it is related to GC and 
memory allocation).
For example, if my d-function just returns some constant integer, 
java side receives it. core.stdc.stdio also works and allows 
console output, but it's not the case with std.stdio.writeln and 
similar functions.
If I use any d-specific functions my program crashes while 
calling native code with some weird message like following:
"Invalid memory access of location 0x0 rip=addr".

It seems like D is not initialized at all, maybe there is some 
internal function like dinit() which I can call in order to 
activate everything?

Thanks.
Oct 16 2013
next sibling parent reply "Iain Buclaw" <ibuclaw ubuntu.com> writes:
On Wednesday, 16 October 2013 at 10:11:32 UTC, Andrew wrote:
 Hello there!
 I've decided to learn a bit of D, as I am currently Android 
 Developer (mostly C++ <- JNI -> Java), I'm trying to create a D 
 shared library which exports function (with extern (C)) for 
 invocation from Java.
 My .d file contains only a single function returning an int, 
 .java calls this function several times.
 This approach only works if d-function is trivial, e.g. it's 
 not using any D functionality (I believe that it is related to 
 GC and memory allocation).
 For example, if my d-function just returns some constant 
 integer, java side receives it. core.stdc.stdio also works and 
 allows console output, but it's not the case with 
 std.stdio.writeln and similar functions.
 If I use any d-specific functions my program crashes while 
 calling native code with some weird message like following:
 "Invalid memory access of location 0x0 rip=addr".

 It seems like D is not initialized at all, maybe there is some 
 internal function like dinit() which I can call in order to 
 activate everything?

 Thanks.
JNI requires (to some degree) compiler support. This could be done in gdc as backend support is there because of g++ JNI interface to gcj. But it would be some magic module or change to the language to add the Java types to the language. Regards Iain.
Oct 16 2013
next sibling parent "Andrew" <diehertz gmail.com> writes:
On Wednesday, 16 October 2013 at 10:15:17 UTC, Iain Buclaw wrote:
 On Wednesday, 16 October 2013 at 10:11:32 UTC, Andrew wrote:
 Hello there!
 I've decided to learn a bit of D, as I am currently Android 
 Developer (mostly C++ <- JNI -> Java), I'm trying to create a 
 D shared library which exports function (with extern (C)) for 
 invocation from Java.
 My .d file contains only a single function returning an int, 
 .java calls this function several times.
 This approach only works if d-function is trivial, e.g. it's 
 not using any D functionality (I believe that it is related to 
 GC and memory allocation).
 For example, if my d-function just returns some constant 
 integer, java side receives it. core.stdc.stdio also works and 
 allows console output, but it's not the case with 
 std.stdio.writeln and similar functions.
 If I use any d-specific functions my program crashes while 
 calling native code with some weird message like following:
 "Invalid memory access of location 0x0 rip=addr".

 It seems like D is not initialized at all, maybe there is some 
 internal function like dinit() which I can call in order to 
 activate everything?

 Thanks.
JNI requires (to some degree) compiler support. This could be done in gdc as backend support is there because of g++ JNI interface to gcj. But it would be some magic module or change to the language to add the Java types to the language. Regards Iain.
As far as I know, calling C from Java only requires is <jni.h> header. It can mimicked with mere D aliases. I'm currently not talking about calling Java from D, although it could be possible by writing C-wrapper library. I just can't understand why D code compiled as a shared library does not work when called from Java. Why does it (does it?) work when called from C?
Oct 16 2013
prev sibling parent "Andrew" <diehertz gmail.com> writes:
On Wednesday, 16 October 2013 at 10:15:17 UTC, Iain Buclaw wrote:
 On Wednesday, 16 October 2013 at 10:11:32 UTC, Andrew wrote:
 Hello there!
 I've decided to learn a bit of D, as I am currently Android 
 Developer (mostly C++ <- JNI -> Java), I'm trying to create a 
 D shared library which exports function (with extern (C)) for 
 invocation from Java.
 My .d file contains only a single function returning an int, 
 .java calls this function several times.
 This approach only works if d-function is trivial, e.g. it's 
 not using any D functionality (I believe that it is related to 
 GC and memory allocation).
 For example, if my d-function just returns some constant 
 integer, java side receives it. core.stdc.stdio also works and 
 allows console output, but it's not the case with 
 std.stdio.writeln and similar functions.
 If I use any d-specific functions my program crashes while 
 calling native code with some weird message like following:
 "Invalid memory access of location 0x0 rip=addr".

 It seems like D is not initialized at all, maybe there is some 
 internal function like dinit() which I can call in order to 
 activate everything?

 Thanks.
JNI requires (to some degree) compiler support. This could be done in gdc as backend support is there because of g++ JNI interface to gcj. But it would be some magic module or change to the language to add the Java types to the language. Regards Iain.
I was talking about calling D from Java in following fashion: https://gist.github.com/DieHertz/7005898 Java calls dinit in static initializer after loading shader library and then proceeds with calling dget.
Oct 16 2013
prev sibling next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 16 October 2013 at 10:11:32 UTC, Andrew wrote:
 Hello there!
 I've decided to learn a bit of D, as I am currently Android 
 Developer (mostly C++ <- JNI -> Java), I'm trying to create a D 
 shared library which exports function (with extern (C)) for 
 invocation from Java.
 My .d file contains only a single function returning an int, 
 .java calls this function several times.
 This approach only works if d-function is trivial, e.g. it's 
 not using any D functionality (I believe that it is related to 
 GC and memory allocation).
 For example, if my d-function just returns some constant 
 integer, java side receives it. core.stdc.stdio also works and 
 allows console output, but it's not the case with 
 std.stdio.writeln and similar functions.
 If I use any d-specific functions my program crashes while 
 calling native code with some weird message like following:
 "Invalid memory access of location 0x0 rip=addr".

 It seems like D is not initialized at all, maybe there is some 
 internal function like dinit() which I can call in order to 
 activate everything?

 Thanks.
Try using Runtime.init() from core.runtime
Oct 16 2013
parent reply "Andrew" <diehertz gmail.com> writes:
On Wednesday, 16 October 2013 at 10:41:35 UTC, John Colvin wrote:
 On Wednesday, 16 October 2013 at 10:11:32 UTC, Andrew wrote:
 Hello there!
 I've decided to learn a bit of D, as I am currently Android 
 Developer (mostly C++ <- JNI -> Java), I'm trying to create a 
 D shared library which exports function (with extern (C)) for 
 invocation from Java.
 My .d file contains only a single function returning an int, 
 .java calls this function several times.
 This approach only works if d-function is trivial, e.g. it's 
 not using any D functionality (I believe that it is related to 
 GC and memory allocation).
 For example, if my d-function just returns some constant 
 integer, java side receives it. core.stdc.stdio also works and 
 allows console output, but it's not the case with 
 std.stdio.writeln and similar functions.
 If I use any d-specific functions my program crashes while 
 calling native code with some weird message like following:
 "Invalid memory access of location 0x0 rip=addr".

 It seems like D is not initialized at all, maybe there is some 
 internal function like dinit() which I can call in order to 
 activate everything?

 Thanks.
Try using Runtime.init() from core.runtime
Wow, thanks! Now everything works, proving that my guess on uninitialized runtime was correct. It's actually Runtime.initialize() according to documentation, by the way.
Oct 16 2013
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 16 October 2013 at 10:53:28 UTC, Andrew wrote:
 On Wednesday, 16 October 2013 at 10:41:35 UTC, John Colvin 
 wrote:
 On Wednesday, 16 October 2013 at 10:11:32 UTC, Andrew wrote:
 Hello there!
 I've decided to learn a bit of D, as I am currently Android 
 Developer (mostly C++ <- JNI -> Java), I'm trying to create a 
 D shared library which exports function (with extern (C)) for 
 invocation from Java.
 My .d file contains only a single function returning an int, 
 .java calls this function several times.
 This approach only works if d-function is trivial, e.g. it's 
 not using any D functionality (I believe that it is related 
 to GC and memory allocation).
 For example, if my d-function just returns some constant 
 integer, java side receives it. core.stdc.stdio also works 
 and allows console output, but it's not the case with 
 std.stdio.writeln and similar functions.
 If I use any d-specific functions my program crashes while 
 calling native code with some weird message like following:
 "Invalid memory access of location 0x0 rip=addr".

 It seems like D is not initialized at all, maybe there is 
 some internal function like dinit() which I can call in order 
 to activate everything?

 Thanks.
Try using Runtime.init() from core.runtime
Wow, thanks! Now everything works, proving that my guess on uninitialized runtime was correct.
No problem.
 It's actually Runtime.initialize() according to documentation, 
 by the way.
Ah yeah, sorry I misremembered.
Oct 16 2013
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-10-16 12:53, Andrew wrote:

 Wow, thanks! Now everything works, proving that my guess on
 uninitialized runtime was correct.
 It's actually Runtime.initialize() according to documentation, by the way.
If you're calling it from C it might be more correct to call this function: https://github.com/D-Programming-Language/druntime/blob/master/src/rt/dmain2.d#L161 It's what Runtime.initialize calls. -- /Jacob Carlborg
Oct 16 2013
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 16 October 2013 at 11:01:33 UTC, Jacob Carlborg 
wrote:
 On 2013-10-16 12:53, Andrew wrote:

 Wow, thanks! Now everything works, proving that my guess on
 uninitialized runtime was correct.
 It's actually Runtime.initialize() according to documentation, 
 by the way.
If you're calling it from C it might be more correct to call this function: https://github.com/D-Programming-Language/druntime/blob/master/src/rt/dmain2.d#L161 It's what Runtime.initialize calls.
Agreed. You can't call Runtime.initialize from outside D due to name mangling (and maybe ABI, depending on your system). However, other than that it really makes no difference which you call, Runtime.initialize is just a no-op wrapper around rt_init.
Oct 16 2013
prev sibling parent "Andrew" <diehertz gmail.com> writes:
On Wednesday, 16 October 2013 at 11:01:33 UTC, Jacob Carlborg 
wrote:
 On 2013-10-16 12:53, Andrew wrote:

 Wow, thanks! Now everything works, proving that my guess on
 uninitialized runtime was correct.
 It's actually Runtime.initialize() according to documentation, 
 by the way.
If you're calling it from C it might be more correct to call this function: https://github.com/D-Programming-Language/druntime/blob/master/src/rt/dmain2.d#L161 It's what Runtime.initialize calls.
Thanks for advice, I'll use it when I'm interfacing C with D :-) For now I can't use it directly because a native function called from java requires a name with "Java_" prefix, so I'd have to write a wrapper with such prefix anyway.
Oct 16 2013
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
Would you mind posting your example code? I'm supposed to be 
exploring using D on android myself next week and a little kick 
to help get started would be cool; I've never actually done any 
android stuff.

As I understand it though, you aren't supposed to use native code 
for the bulk of the app which sucks. But still some D is better 
than no D.
Oct 16 2013
parent reply "Andrew" <diehertz gmail.com> writes:
On Wednesday, 16 October 2013 at 13:31:50 UTC, Adam D. Ruppe 
wrote:
 Would you mind posting your example code? I'm supposed to be 
 exploring using D on android myself next week and a little kick 
 to help get started would be cool; I've never actually done any 
 android stuff.

 As I understand it though, you aren't supposed to use native 
 code for the bulk of the app which sucks. But still some D is 
 better than no D.
I don't mind, but the code is currently Java + D without any Android. I can post it in such state, the only thing that keeps me from moving it to Android is absence of D compiler with ARM back-end (though I'm sure it exists and I have even seen some articles about building D for ARM and Android). Concluding, I can post the could if you like, or I can first try compiling it for ARM :-) You're not supposed to use native code in Android, right, but many companies do. The company I work for uses C++ in order to make project cross-platform between iOS and Android.
Oct 16 2013
next sibling parent "Andrew" <andrew nowhere.com> writes:
 Concluding, I can post the could if you like, or I can first 
 try compiling it for ARM :-)
This might help :- http://forum.dlang.org/post/dpzvxpncqabzxebgdmuq forum.dlang.org
Oct 17 2013
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 16 October 2013 at 14:39:23 UTC, Andrew wrote:
 Concluding, I can post the could if you like, or I can first 
 try compiling it for ARM :-)
whatever's easiest for you. I have an arm cross compiler targeting the raspberry pi, not sure if that will work for the android device or not, I'll try it later (the device arrived yesterday, but I haven't had much of a chance to play with it yet). But I've never done JNI before either, so I'm starting more or less from scratch here.
Oct 24 2013
prev sibling parent "Daniel Kozak" <kozzi11 gmail.com> writes:
On Wednesday, 16 October 2013 at 10:11:32 UTC, Andrew wrote:
 Hello there!
 I've decided to learn a bit of D, as I am currently Android 
 Developer (mostly C++ <- JNI -> Java), I'm trying to create a D 
 shared library which exports function (with extern (C)) for 
 invocation from Java.
 My .d file contains only a single function returning an int, 
 .java calls this function several times.
 This approach only works if d-function is trivial, e.g. it's 
 not using any D functionality (I believe that it is related to 
 GC and memory allocation).
 For example, if my d-function just returns some constant 
 integer, java side receives it. core.stdc.stdio also works and 
 allows console output, but it's not the case with 
 std.stdio.writeln and similar functions.
 If I use any d-specific functions my program crashes while 
 calling native code with some weird message like following:
 "Invalid memory access of location 0x0 rip=addr".

 It seems like D is not initialized at all, maybe there is some 
 internal function like dinit() which I can call in order to 
 activate everything?

 Thanks.
I just came here to ask same question :D
Oct 16 2013