- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi all,
For some reason, I have to invoke several Fortran dlls using JavaScript, and I've met problems when I tried to pass a character variable to Fortran.
The following is the dll and corresponding Fortran codes (x64):
!-------------------------------------------------------------------------------------------
character(len=1) function pass(inStr,inLen)
!DEC$ ATTRIBUTES C,DLLEXPORT::pass
implicit none
character(len=1),intent(in)::inStr
integer,intent(in)::inLen
character(len=1)::tempStr
pass=inStr
end function
!-------------------------------------------------------------------------------------------
And I invoke the dll in JavaScript like this (by means of no-ffi):
//-------------------------------------------------------------------------------------------
const dllPath = path.join(__dirname, '../../dlls/PassStr.dll')
var DLL = ffi.Library(dllPath, {
'pass':['string', ['string', 'int']]
})
DLL.pass.async("A", 1, (err, result) => {
})
//-------------------------------------------------------------------------------------------
But the dll cannot catch the character. I've heard that it may due to the character encoding i.e. UTF-8/Unicode, but I don't really know how to solve the problem. So anybody has some comments?
Thank a lot!
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think this is more of an issue that you have not declared the function "pass" arguments properly in your JavaScript.
The Fortran function "pass" is declared as returning the address of a 1 byte character, that takes as arguments the address of a 1 byte character, and the address/reference of a 4-byte integer containing the length (1) of the one byte character referebce a Jav
I am not a Java programmer, I have used C#, it appears that you have declared the interface as:
returning a string object (which may or may not be Unicode, which contains reference/pointer to characters, plus string length)
taking as arguments a reference to a Java string object, and a reference to an integer. It is unknown to me as to if int in Java is 16, 32 or 64 bits.
I would look at experimenting with calling a C function with signature of
char* test(char* cp, int* len);
Once that is working then rework it to call your pass function.
I think your pass function needs to be declared as
character(len=*) function pass(inStr,inLen) !DEC$ ATTRIBUTES C,DLLEXPORT::pass implicit none character(len=*),intent(in)::inStr integer,intent(in)::inLen character(len=1024), save ::tempStr ! caution only 1 copy in SAVE tempStr = "This is a test" pass=tempStr // ":" // inStr(1:inLen) ! "This is a test:whatWasIninStr" end function
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Notes, make the one copy of the tempStr long enough to contain the maximum number of possible characters. You can make this an allocatable if need be. On the Java side, declare the function return as returning a reference to fixed length character buffer (same worst case length) that accepts the return arg. Then convert (copy) the trailing space trimmed result as a Java string. It may be better to define the function as a subroutine (void function) that has arguments (inStr, inLen, outStr, outLen) and thus you do not have to change the Fortran DLL should you decide to increase the Java maximum string lengths. This also eliminates the requirement of having a single buffer for holding the return argument.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Eugene and Jim,
Thank you for your comments!
First of all, I have to say that I'm not a JavaScript programmer either. I have tried to test your solutions. As for Jim's suggestion, ( character(len=*) function pass(inStr,inLen) ), Fortran cannot catch the content of inStr either. If I print "inStr" in the Fortran function "pass", I can see nothing just like I only define character(len=*)::inStr but don't initialize it. What's worse, when I tried to test Eugene's suggestion, I found that the Fortran dll even cannot receive the content of an integer array sent by JavaScript.
There is a great possibility that the inconsistency between the data structure of Fortran and JavaScript leads to this problem. I'm still trying to fix it. I'll be very appreciated if you and anyone else can give me further comments.
Thank you all!
Xudong Li
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>DLL.pass.async("A", 1, (err, result) =>{});
The first argument is a reference to a Java string object and not a reference to a block of data containing characters.
char buffer[] = new char [1024]; // big enough for your later use
buffer[0] = 'A'; // don't care about [1], [2], ...
DLL.pass.async(buffer, 1, (err, result) =>{}); // Java may want {;}
I do not know if the 1 above is passed by value or reference, you will need to check this out and correct.
Jim Dempsey

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