- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello:
I am having some trouble passing arrays of characters between Java and Fortran. The Java code calls a DLL written in Fortran.
I want to test the following: Pass a 5-element array of 8-character strings from Java to Fortran, then test each element k of the character vector against a certain string value, and set an integer vector with each element k equal either to 1 (equality) or 0 (non-equality), and pass back the array of integers from Fortran to Java.
There seems to be some kind of mis-alignment, because I do see that there is a lot of garbage before and in between the character strings, but the elements of the character vector do seem to be there, and for the appropriate elements where equality is supposed to happen, the integer vector is set accordingly. So what is the extraneous garbage??
In the code attached below I have been testing some code incrementally. The calls to achieve what I am testing corresponds to the calls to the last one, foostr4 (aka strpass4).
Is there a particular convention about passing strings between Java and Fortran that might explain the garbage between the strings??
Can anybody help?
Bruno Repetto, PhD
--------------
This is the Java code:
package jna_test;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.ptr.IntByReference;
public class Main {
public interface F95Test extends com.sun.jna.Library{
F95Test lib=(F95Test) Native.loadLibrary("libf90", F95Test.class);
boolean foostr(String s, IntByReference len);
boolean foostr2(String s);
boolean foostr3(String s);
void foostr4(String s[],int b[], IntByReference len);
}
public static void main(String[] args) {
String testString = "str_test";
IntByReference len= new IntByReference(testString.length());
boolean strResult =F95Test.lib.foostr(testString, len);
System.out.println ("len: " + len.getValue());
System.out.println("strResult: " + strResult);
System.out.println("Strpass2: " + F95Test.lib.foostr2(testString));
System.out.println("Strpas3: " + F95Test.lib.foostr3(testString));
final String[] severalStrings={"abcdefgh", "str_test","12345678", "a1b2c3d4","hgfedcba"};
int[] vals={9,9,9,9,9};
len=new IntByReference(5);
F95Test.lib.foostr4(severalStrings, vals, len);
for(int i=0;i<5;i++){
System.out.println(vals);
}
}
}
This is the Fortran code (a mixture of F90 and F77, which is on purpose!)
FUNCTION strpass(line, b)
!DEC$ ATTRIBUTES ALIAS: 'foostr', DLLEXPORT :: strpass
INTEGER :: b
CHARACTER(len=b) :: line
LOGICAL :: strpass
strpass = (line == 'str_test') .AND. (b == 8)
print *,'line= ',line,' len= ',b
END FUNCTION
FUNCTION strpass2(line)
!DEC$ ATTRIBUTES ALIAS: 'foostr2', DLLEXPORT :: strpass2
CHARACTER(len=8) :: line
LOGICAL :: strpass2
strpass2 = (line == 'str_test')
print *,'line= ',line,' strpass2=',strpass2
END FUNCTION
logical FUNCTION strpass3(line)
!DEC$ ATTRIBUTES ALIAS: 'foostr3', DLLEXPORT :: strpass3
CHARACTER*8 line
strpass3=line.eq.'str_test'
print *,'line= ',line,' strpass3=',strpass3
END
subroutine strpass4(line,flag,n)
!DEC$ ATTRIBUTES ALIAS: 'foostr4', DLLEXPORT :: strpass4
implicit none
CHARACTER*8 line(*)
integer flag(*),n,i
do i=1,n
if(line(i).eq.'str_test')then
flag(i)=1
else
flag(i)=0
endif
print *,'strpass4:(',i,')line= ',line(i),' flag=',flag(i)
enddo
END
And below is the output of the Java run.
run:
line= str_test len= 8
len:8
strResult: true
line= str_test strpass2= T
Strpass2: true
line= str_test strpass3= T
Strpas3: true
strpass4:( 1 )line= flag= 0
strpass4:( 2 )line= flag= 0
strpass4:( 3 )line= 8 flag= 0
strpass4:( 4 )line= V- flag= 0
strpass4:( 5 )line= abcdefgh flag= 0
0
0
0
0
0
BUILD SUCCESSFUL (total time: 1 second)
I am having some trouble passing arrays of characters between Java and Fortran. The Java code calls a DLL written in Fortran.
I want to test the following: Pass a 5-element array of 8-character strings from Java to Fortran, then test each element k of the character vector against a certain string value, and set an integer vector with each element k equal either to 1 (equality) or 0 (non-equality), and pass back the array of integers from Fortran to Java.
There seems to be some kind of mis-alignment, because I do see that there is a lot of garbage before and in between the character strings, but the elements of the character vector do seem to be there, and for the appropriate elements where equality is supposed to happen, the integer vector is set accordingly. So what is the extraneous garbage??
In the code attached below I have been testing some code incrementally. The calls to achieve what I am testing corresponds to the calls to the last one, foostr4 (aka strpass4).
Is there a particular convention about passing strings between Java and Fortran that might explain the garbage between the strings??
Can anybody help?
Bruno Repetto, PhD
--------------
This is the Java code:
package jna_test;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.ptr.IntByReference;
public class Main {
public interface F95Test extends com.sun.jna.Library{
F95Test lib=(F95Test) Native.loadLibrary("libf90", F95Test.class);
boolean foostr(String s, IntByReference len);
boolean foostr2(String s);
boolean foostr3(String s);
void foostr4(String s[],int b[], IntByReference len);
}
public static void main(String[] args) {
String testString = "str_test";
IntByReference len= new IntByReference(testString.length());
boolean strResult =F95Test.lib.foostr(testString, len);
System.out.println ("len: " + len.getValue());
System.out.println("strResult: " + strResult);
System.out.println("Strpass2: " + F95Test.lib.foostr2(testString));
System.out.println("Strpas3: " + F95Test.lib.foostr3(testString));
final String[] severalStrings={"abcdefgh", "str_test","12345678", "a1b2c3d4","hgfedcba"};
int[] vals={9,9,9,9,9};
len=new IntByReference(5);
F95Test.lib.foostr4(severalStrings, vals, len);
for(int i=0;i<5;i++){
System.out.println(vals);
}
}
}
This is the Fortran code (a mixture of F90 and F77, which is on purpose!)
FUNCTION strpass(line, b)
!DEC$ ATTRIBUTES ALIAS: 'foostr', DLLEXPORT :: strpass
INTEGER :: b
CHARACTER(len=b) :: line
LOGICAL :: strpass
strpass = (line == 'str_test') .AND. (b == 8)
print *,'line= ',line,' len= ',b
END FUNCTION
FUNCTION strpass2(line)
!DEC$ ATTRIBUTES ALIAS: 'foostr2', DLLEXPORT :: strpass2
CHARACTER(len=8) :: line
LOGICAL :: strpass2
strpass2 = (line == 'str_test')
print *,'line= ',line,' strpass2=',strpass2
END FUNCTION
logical FUNCTION strpass3(line)
!DEC$ ATTRIBUTES ALIAS: 'foostr3', DLLEXPORT :: strpass3
CHARACTER*8 line
strpass3=line.eq.'str_test'
print *,'line= ',line,' strpass3=',strpass3
END
subroutine strpass4(line,flag,n)
!DEC$ ATTRIBUTES ALIAS: 'foostr4', DLLEXPORT :: strpass4
implicit none
CHARACTER*8 line(*)
integer flag(*),n,i
do i=1,n
if(line(i).eq.'str_test')then
flag(i)=1
else
flag(i)=0
endif
print *,'strpass4:(',i,')line= ',line(i),' flag=',flag(i)
enddo
END
And below is the output of the Java run.
run:
line= str_test len= 8
len:8
strResult: true
line= str_test strpass2= T
Strpass2: true
line= str_test strpass3= T
Strpas3: true
strpass4:( 1 )line= flag= 0
strpass4:( 2 )line= flag= 0
strpass4:( 3 )line= 8 flag= 0
strpass4:( 4 )line= V- flag= 0
strpass4:( 5 )line= abcdefgh flag= 0
0
0
0
0
0
BUILD SUCCESSFUL (total time: 1 second)
Link Copied
2 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Based on what I know (which for Java mostly came off the back of a cereal box) a String array (String[]) is going to turn up on the fortran side as an array of C pointer-to-char, with each element in the array pointing to one string. This is very different from the fortran concept of a character variable that is an array, which is just a whole heap of characters in array element order, that might be passed around in an implementation as a single pointer to the first character.
(Note that all elements in a fortran array of character have the same length, is that the case for Java?)
If your procedure on the fortran side morphed to something like the following untested code:
...I wonder how you'd go. You may need to experiment further with the level of indirection and all that.
Note the inclusion of the BIND and ISO_C_BINDING stuff. You ask about a Java-to-Fortran "convention". There isn't even a formal Fortran-to-Fortran convention for much of this stuff! But there is a formal Fortran-C convention, if you apply the appropriate attributes. And there's probably a "formal" Java-C convention as part of this jna thing. Relying on this more formal link seems like a much more robust solution to me - and it will be far easier for you to work out what's going wrong when you get issues like this.
(Practically you could get by without relying on the BIND(C) stuff, and many do, but since it is there I see no point in not using it (and a subset of those who do rely on it end up posting "why is it now broken?" questions here when something implementation related gets changed...)).
(Note that all elements in a fortran array of character have the same length, is that the case for Java?)
If your procedure on the fortran side morphed to something like the following untested code:
[fortran]SUBROUTINE strpass4a(ptr_array) BIND(C, NAME='strpass4a')
!DEC$ ATTRIBUTES DLLEXPORT :: strpass4a
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR, C_PTR, C_F_POINTER
IMPLICIT NONE
TYPE(C_PTR), INTENT(IN) :: ptr_array(*)
CHARACTER(8,KIND=C_CHAR), POINTER :: s
INTEGER :: i
!***
DO i = 1, 5
CALL C_F_POINTER(ptr_array(i), s)
PRINT *, s
END DO
END SUBROUTINE strpass4a
[/fortran]
...I wonder how you'd go. You may need to experiment further with the level of indirection and all that.
Note the inclusion of the BIND and ISO_C_BINDING stuff. You ask about a Java-to-Fortran "convention". There isn't even a formal Fortran-to-Fortran convention for much of this stuff! But there is a formal Fortran-C convention, if you apply the appropriate attributes. And there's probably a "formal" Java-C convention as part of this jna thing. Relying on this more formal link seems like a much more robust solution to me - and it will be far easier for you to work out what's going wrong when you get issues like this.
(Practically you could get by without relying on the BIND(C) stuff, and many do, but since it is there I see no point in not using it (and a subset of those who do rely on it end up posting "why is it now broken?" questions here when something implementation related gets changed...)).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ian:
Thanks for your suggestion. I will try this and report back.
Snowed-in-in-Seattle,
Bruno
Thanks for your suggestion. I will try this and report back.
Snowed-in-in-Seattle,
Bruno

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page