Re: Fortran DLL and D

2012-03-21 Thread Michael

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

2012-03-21 Thread bearophile

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

2012-03-21 Thread Michael

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

2012-03-14 Thread Ellery Newcomer

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

2012-03-13 Thread Michael

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

2012-03-13 Thread Tobias Brandt
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

2012-03-13 Thread Andrej Mitrovic
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

2012-03-13 Thread Michael

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

2012-03-13 Thread Tobias Brandt
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

2012-03-13 Thread Michael

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

2012-03-13 Thread Michael

Thanks, but i still get the same.