- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What is the good method to pass delphi strings to a fortran subroutine ?
Link Copied
6 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - aharel
What is the good method to pass delphi strings to a fortran subroutine ?
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
...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
...
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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