Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

passing delphi string to fortran

aharel
Beginner
740 Views
What is the good method to pass delphi strings to a fortran subroutine ?
0 Kudos
6 Replies
gib
New Contributor II
740 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
740 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
740 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
740 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
740 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
740 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