digitalmars.D - Fortran DLL and D
- Michael (45/45) Mar 13 2012 Hi everyone)
- Tobias Brandt (5/5) Mar 13 2012 Fortran uses pass-by-ref by default. You could try
- Michael (16/21) Mar 13 2012 in case integer, value :: i or integer, intent(in) :: i
- Tobias Brandt (10/36) Mar 13 2012 You could use the C binding syntax:
- Michael (1/1) Mar 13 2012 Thanks, but i still get the same.
- Andrej Mitrovic (5/5) Mar 13 2012 I don't think this can work:
- Michael (12/18) Mar 13 2012 I know, it's short version.
- Ellery Newcomer (13/17) Mar 14 2012 Here's apples to oranges, since I'm on linux 64 bit, but with your code
- Michael (87/87) Mar 21 2012 Guys, thanks for advices.
- bearophile (4/6) Mar 21 2012 Why don't you write how to do it in the D wiki?
- Michael (2/8) Mar 21 2012
Hi everyone)
dmd 2.058
os: win 7 64 bit
fortran compilers: gfortran, ftn95
I have a fortran code that compiled into dll:
SUBROUTINE fsu (i)
real :: x
integer :: i
x = 0.025
print *, 'The answer is x = ', x , i
END SUBROUTINE fsu
and simple D code
import std.stdio;
import core.runtime;
import std.c.windows.windows;
import core.memory;
alias void function(int) MyHandler;
void main()
{
GC.disable;
FARPROC fp;
HMODULE lib = cast(HMODULE)Runtime.loadLibrary("testf.dll");
MyHandler mh;
if (lib is null)
{
writeln("Lib!");
return;
}
fp = GetProcAddress(lib, "FSU");
if (fp is null)
{
writeln("Proc!");
writeln(GetLastError());
return;
}
mh = cast(MyHandler) fp;
(*mh)(1);
Runtime.unloadLibrary(lib);
}
and its output
The answer is x = 2.500000E-02 1407551829
It's should be an 1 value instead 1407551829.
I think, trouble in param passing.
How it can be fixed? Or where to look?
Thanks)
Mar 13 2012
Fortran uses pass-by-ref by default. You could try
integer, value :: i
in the Fortran function declaration, OR
*int
in the MyHandler declaration.
Mar 13 2012
On Tuesday, 13 March 2012 at 22:30:02 UTC, Tobias Brandt wrote:
Fortran uses pass-by-ref by default. You could try
integer, value :: i
in the Fortran function declaration, OR
*int
in the MyHandler declaration.
in case integer, value :: i or integer, intent(in) :: i
same results
in case int*
int * i;
*i=5;
(*mh)(i);
object.Error: Access Violation
----------------
409960
4097D7
402BA8
402BE7
4027F7
413635
----------------
Mar 13 2012
On 13 March 2012 23:53, Michael <pr m1xa.com> wrote:On Tuesday, 13 March 2012 at 22:30:02 UTC, Tobias Brandt wrote:You could use the C binding syntax: SUBROUTINE fsu (i) bind(C, name =3D "FSU") real :: x integer, value :: i x =3D 0.025 print *, 'The answer is x =3D ', x , i END SUBROUTINE fsu and then use extern(C) in D. That should work, but you need a newish Fortran compiler.Fortran uses pass-by-ref by default. You could try =A0 =A0integer, value :: i in the Fortran function declaration, OR =A0 =A0*int in the MyHandler declaration.in case integer, value :: i or integer, intent(in) :: i same results in case int* int * i; *i=3D5; (*mh)(i); object.Error: Access Violation ---------------- 409960 4097D7 402BA8 402BE7 4027F7 413635 ----------------
Mar 13 2012
I don't think this can work: alias void function(int) MyHandler; maybe: alias extern(C) void function(int) MyHandler; And there's no need to call it like this: '(*mh)(1)', call it mh(1).
Mar 13 2012
On Tuesday, 13 March 2012 at 22:42:38 UTC, Andrej Mitrovic wrote:I don't think this can work: alias void function(int) MyHandler; maybe: alias extern(C) void function(int) MyHandler; And there's no need to call it like this: '(*mh)(1)', call it mh(1).I know, it's short version. Anyway, object.Error: Access Violation ---------------- 409960 4097D7 402BA8 402BE7 4027F7 413635 ----------------
Mar 13 2012
On 03/13/2012 05:15 PM, Michael wrote:Hi everyone) dmd 2.058 os: win 7 64 bit fortran compilers: gfortran, ftn95Here's apples to oranges, since I'm on linux 64 bit, but with your code and this: pragma(lib, "flib"); extern(C) void fsu_(int*i); void main(){ int i = 1; fsu_(&i); } when compiled on my box gives The answer is x = 2.50000004E-02 1 If something similar doesn't work for you, can you post disassembly dumps of your dll function and calling function?
Mar 14 2012
Guys, thanks for advices.
After all I have proper code.
simple.d
import core.runtime;
import std.stdio;
import std.string;
import std.conv;
version(Windows)
{
import core.sys.windows.windows;
alias GetProcAddress GetProc;
}
else
version(Linux) // not tested
{
import core.sys.linux.linux;
alias dlsym GetProc;
}
alias extern(C) void function (double *, int) func_One;
alias extern(C) void function (double *, int, ref int) func_Two;
void main(string[] args)
{
if (args.count != 2)
return;
size_t size = parse!int(args[1]);
writeln("Accept: ", size);
double[] arr = new double[size];
auto dllfile = "simple.dll";
void * lib = Runtime.loadLibrary(dllfile);
if (!lib)
{
writeln("Lib!");
return;
}
func_One f_One = cast(func_One) GetProc(lib,
"fOne".toStringz);
if (f_One is null)
{
writeln("f_One!");
return;
}
func_Two f_Two = cast(func_Two) GetProc(lib,
"fTwo".toStringz);
if (f_Two is null)
{
writeln("f_Two!");
return;
}
f_One(arr.ptr, arr.length);
writeln("array size: ", arr.length);
for(int k = 0; k < arr.length; k++)
{
writeln(k + 1, '\t', arr[k]);
}
int ans = 0;
f_Two(arr.ptr, arr.length, ans);
writeln("fTwo = ", ans);
Runtime.unloadLibrary(lib);
}
simple.f95 compiled with gfortran -shared -O3 -o simple.dll
simple.f95
subroutine fOne(a, i) bind(C, name = "fOne")
integer*4, value, intent(in) :: i
real*8, dimension(i), intent(out) :: a
print *, 'entry fortran dll'
print *, 'size', i
do j = 1, i
a(j) = j * j;
print *, j
end do
print *, 'exit fortran dll'
end
subroutine fTwo(a, i, ans) bind(C, name = "fTwo")
integer*4, value, intent(in) :: i
real*8, dimension(i), intent(in) :: a
integer*4, intent(out) :: ans
print *, 'entry fortran dll'
print *, 'size', i
if (a(1) .lt. 100) then
print *, 'inside if'
ans = 1
print *, 'end if'
return
end if
ans = 0
print *, 'exit fortran dll'
end
Mar 21 2012
Michael wrote:Guys, thanks for advices. After all I have proper code.Why don't you write how to do it in the D wiki? Bye, bearophile
Mar 21 2012
Bad English, and I don't have experiense with Wiki. On Wednesday, 21 March 2012 at 22:21:11 UTC, bearophile wrote:Michael wrote:Guys, thanks for advices. After all I have proper code.Why don't you write how to do it in the D wiki? Bye, bearophile
Mar 21 2012









"Michael" <pr m1xa.com> 