JNA String array issue

412 views
Skip to first unread message

Janko Sokolovic

unread,
Jul 30, 2014, 9:53:19 AM7/30/14
to jna-...@googlegroups.com
I have a fortran subroutine, which I want to wrap via jna.

I have created a dll from fortran file and subroutine's input parameter is string array (i.e. Character*8 arr(3))
So when I try to call it via jna, if Im not doing anything that changes the array's values, it doesn't crash, but when I change anything, i.e.  arr(1) = "new_str" (in fortran) and then try to call it via jna, it throws illegal memory access..
I know that for regular strings i can use byte[]  and it works fine, but JNA doesn't allow byte[][] which would probably handle this issue correctly..

So I've tried with String[] and StringArray, and even Pointer, but whenever I try to change the value of array's elements inside fortran's dll, I get an error with memorry access issue, while passing string as byte[] and changing it, goes well w/o issues..

Here's the example Im working on

FORTRAN:

SUBROUTINE STRARR(arr)
CHARACTER*8 :: arr(3)
arr(1)="newstr11"
arr(2)="newstr22"
arr(3)="newstr33"
END SUBROUTINE

JAVA:

interface F95Test extends com.sun.jna.Library {
        F95Test lib = (F95Test) Native.loadLibrary("strarrtest", F95Test.class); // strarrtest is dll with the fortran subroutine

        void STRARR(StringArray line);
    }

 public static void main(String[] args) throws UnsupportedEncodingException {
        String[] a = {"str_tes1", "str_tes2", "str_tes3"};
       
        StringArray sa =  new StringArray(a);

        F95Test.lib.STRARR(sa); //this is where it crashes with illegal memory access

        for ( String az : a ) System.out.println(az);

    }

Hope it's clear enough, I feel there's a simple solution for this, but I just can't seem to grab it yet..
Cheers

Timothy Wall

unread,
Jul 31, 2014, 7:46:38 AM7/31/14
to jna-...@googlegroups.com
A writable byte buffer is not the same as a string. You can only use String for `const char*`; if your target writes back to the buffer you need to use `byte[]` or `char[]` instead (depending on your native character type).

After your native call, you can use Native.toString(byte[]) to convert a NUL-terminated byte array back into a String with proper decoding (if any).
> --
> You received this message because you are subscribed to the Google Groups "Java Native Access" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Timothy Wall

unread,
Jul 31, 2014, 7:49:34 AM7/31/14
to jna-...@googlegroups.com
Oops, sorry I misread that.

Same thing goes for string arrays, though. What you’ve actually got is an array of Pointer, so start with that (Pointer[]) and initialize each element with a com.sun.jna.Memory element of the appropriate size, e.g.

Pointer[] array = new Pointer[] {
new Memory(3), new Memory(3), …, new Memory(3)
}

Pointer.getString(0) on each element will then pull back whatever the native side wrote.


On Jul 30, 2014, at 9:53 AM, Janko Sokolovic <jankoso...@gmail.com> wrote:

Janko Sokolovic

unread,
Aug 1, 2014, 9:11:21 AM8/1/14
to jna-...@googlegroups.com
But how do I set the values of my strings now and send them as parameters ?
i.e strings are   {"one", "two", "thr"}
now i create Pointer[] array {
    new Memory(3), new Memory(3), new Memory(3)
}

and I tried array[0].setString(0, "one"); // but this gives me outofboundsexception, says that offset is 4 even though it is 0?!

Janko Sokolović



On 31 July 2014 13:49, Timothy Wall <twal...@java.net> wrote:
Oops, sorry I misread that.

Same thing goes for string arrays, though.  What you've actually got is an array of Pointer, so start with that (Pointer[]) and initialize each element with a com.sun.jna.Memory element of the appropriate size, e.g.

Pointer[] array = new Pointer[] {
    new Memory(3), new Memory(3), ..., new Memory(3)
You received this message because you are subscribed to a topic in the Google Groups "Java Native Access" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jna-users/GaAvJ3KPtSU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jna-users+...@googlegroups.com.

Marco Trudel

unread,
Aug 1, 2014, 10:35:28 AM8/1/14
to jna-...@googlegroups.com
Or, using our native interfacing approach [1]:

Container<String8> c = new Container<String8>(3){};

That's all.
Ok, I'll stop doing advertising now :-)

Cheers!
Marco

[1] https://groups.google.com/forum/#!topic/jna-users/tZtKg7e-jTE


On 07/31/2014 01:49 PM, Timothy Wall wrote:
> Oops, sorry I misread that.
>
> Same thing goes for string arrays, though. What you've actually got is an array of Pointer, so start with that (Pointer[]) and initialize each element with a com.sun.jna.Memory element of the appropriate size, e.g.
>
> Pointer[] array = new Pointer[] {
> new Memory(3), new Memory(3), ..., new Memory(3)

Timothy Wall

unread,
Aug 1, 2014, 12:05:23 PM8/1/14
to jna-...@googlegroups.com
Just allocate one more byte per buffer to account for the NUL terminator in each string. The receiving end won’t likely care that there’s an extra byte available.
Reply all
Reply to author
Forward
0 new messages