Re: Fortran DLL and D
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
Re: Fortran DLL and D
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
Re: Fortran DLL and D
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
Re: Fortran DLL and D
On 03/13/2012 05:15 PM, Michael wrote: Hi everyone) dmd 2.058 os: win 7 64 bit fortran compilers: gfortran, ftn95 Here'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.5004E-02 1 If something similar doesn't work for you, can you post disassembly dumps of your dll function and calling function?
Fortran DLL and D
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.50E-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)
Re: Fortran DLL and D
Fortran uses pass-by-ref by default. You could try integer, value :: i in the Fortran function declaration, OR *int in the MyHandler declaration.
Re: Fortran DLL and D
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).
Re: Fortran DLL and D
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
Re: Fortran DLL and D
On 13 March 2012 23:53, Michael p...@m1xa.com wrote: 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 You could use the C binding syntax: SUBROUTINE fsu (i) bind(C, name = FSU) real :: x integer, value :: i x = 0.025 print *, 'The answer is x = ', x , i END SUBROUTINE fsu and then use extern(C) in D. That should work, but you need a newish Fortran compiler.
Re: Fortran DLL and D
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
Re: Fortran DLL and D
Thanks, but i still get the same.