Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29285 Discussions

passing delphi string to fortran

aharel
Beginner
1,419 Views
What is the good method to pass delphi strings to a fortran subroutine ?
0 Kudos
6 Replies
gib
New Contributor II
1,419 Views
Quoting - aharel
What is the good method to pass delphi strings to a fortran subroutine ?
This is some code I've extracted from programs I wrote many years ago. Don't ask me to explain the Delphi side (I was never expert) or the !DEC$ ATTRIBUTES stuff. This looks a bit complicated, but it does work. In this case the Fortran code was in a DLL that the Delphi code accessed.

Define a type called TFortString, which holds a pointer to an array of characters big enough for
your purpose:

{* Delphi code *}

type
TFStr = array[0..127] of char;
TFortString = packed record
ptr: TFStr;
len: DWORD;
end;

procedure Save_Results(var forFilename: TFortString); stdcall;

procedure Save_Results; external 'myfortran.dll' name 'save_results';

...
pasFilename: string;
pasFilename := 'test.out';
forFilename := MakeFortString(pasFilename);
Save_Results(forFilename);
...

{* Sets up the record to hold a Fortran string *}
function MakeFortString(var InString: string): TFortString;

var
TmpStr : TFStr;
begin
FillChar(TmpStr, SizeOf(TmpStr), 32);
StrPCopy(TmpStr, InString);
Result.len := Length(InString);
Result.ptr := TmpStr;
end;


! Fortran code

subroutine Save_Results(resfilename)
!DEC$ ATTRIBUTES REFERENCE :: resfilename
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT :: save_results
!DEC$ ATTRIBUTES ALIAS : "_save_results" :: save_results
character*(128) resfilename
...

0 Kudos
aharel
Beginner
1,419 Views
Quoting - gib
This is some code I've extracted from programs I wrote many years ago. Don't ask me to explain the Delphi side (I was never expert) or the !DEC$ ATTRIBUTES stuff. This looks a bit complicated, but it does work. In this case the Fortran code was in a DLL that the Delphi code accessed.

Define a type called TFortString, which holds a pointer to an array of characters big enough for
your purpose:

{* Delphi code *}

type
TFStr = array[0..127] of char;
TFortString = packed record
ptr: TFStr;
len: DWORD;
end;

procedure Save_Results(var forFilename: TFortString); stdcall;

procedure Save_Results; external 'myfortran.dll' name 'save_results';

...
pasFilename: string;
pasFilename := 'test.out';
forFilename := MakeFortString(pasFilename);
Save_Results(forFilename);
...

{* Sets up the record to hold a Fortran string *}
function MakeFortString(var InString: string): TFortString;

var
TmpStr : TFStr;
begin
FillChar(TmpStr, SizeOf(TmpStr), 32);
StrPCopy(TmpStr, InString);
Result.len := Length(InString);
Result.ptr := TmpStr;
end;


! Fortran code

subroutine Save_Results(resfilename)
!DEC$ ATTRIBUTES REFERENCE :: resfilename
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT :: save_results
!DEC$ ATTRIBUTES ALIAS : "_save_results" :: save_results
character*(128) resfilename
...


I try your solution but it does'nt work at all, I have got anything in my fortran variable.
I don't understand what append.
0 Kudos
aharel
Beginner
1,419 Views
Quoting - aharel

I try your solution but it does'nt work at all, I have got anything in my fortran variable.
I don't understand what append.

More precision about my tests. Here is my code :

! Fortran code

subroutine AstecSaveResult(resfilename)
!DEC$ ATTRIBUTES REFERENCE :: resfilename
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT :: AstecSaveResult
character*(128) resfilename

write(6,*) 'AstecSaveResult = ',resfilename


end




====================

//Delphi code
SaveResProc = procedure(filename : PChar);

hLibrary := LoadLibrary(PChar('mydll.dll'));




outputfic := 'Output.txt';
forFilename := PChar(outputfic);

@SaveResProc := GetProcAddress(hLibrary, PChar('saveresult'));
if @AstecSaveResProc <> nil then
begin
SaveResProc(forFilename);
end;
0 Kudos
Lorri_M_Intel
Employee
1,419 Views

I haven't done Delphi in years, but ... from these code snippets, it looks like you have a name mismatch.

That is, your Fortran code is outputting one name, you're trying to load a different name; I suspect you'd see that the load failed.


- Lorri
0 Kudos
gib
New Contributor II
1,419 Views
Quoting - aharel

I try your solution but it does'nt work at all, I have got anything in my fortran variable.
I don't understand what append.
I think Lorri is right - I don't see that mydll.dll has a procedure called 'saveresult'. You need to look at the !DEC$ statements that I used, in particular the ALIAS clause. Watch for the '_'! (prepend rather than append ;-) This is not a string-passing issue, but a calling-Fortran-subroutine issue.
0 Kudos
gib
New Contributor II
1,419 Views
Quoting - aharel

I try your solution but it does'nt work at all, I have got anything in my fortran variable.
I don't understand what append.
I now see that you ignored MakeFortString, the key to the whole process. Why was that?
0 Kudos
Reply