www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Mixed Language Programming - e**x crashes

reply "R**3" <rrobe71907 aol.com> writes:
Programming old-timer (but D newbie) with an interesting problem. 
  Have been doing some playing around with D (DMD v2.066.0) 
calling FORTRAN.  Asked at the SilverFrost FTN95 Support Forum, 
kicked some ideas around, no differences.  I realize that a 
definitive answer will be difficult since I am combining products 
from 2 different suppliers.

If I have done something that is so ignorant that it is a 
monumental fail, please be gentle ;-).

when the following is used as real function in FORTRAN
main program (ENG0010.exe) the following runs fine
--------------------------

C     Series Resistance Capacitance Circuit
C     Resistance Capacitance Time
C     T : Seconds
C     R : Ohms
C     C : Farads
       REAL FUNCTION ERCT (T, R, C) RESULT (X)
       REAL T, R, C, X
       X = -T / (R * C)
       X = EXP(X)
       RETURN
       END FUNCTION ERCT


when used in a .dll (mathproc.dll) called by a D command line
program (dmath.exe, compiled with DMD dmath.d mathproc.lib),
function crashes at X = EXP(X) with
object.Error (0): Invalid Floating Point Operation
in RegisterWaitForInputIdle

The FORTRAN main program:
       PROGRAM ENG0010
       IMPLICIT NONE

       REAL E, T, R, C, L, I, ERCT, VCAP, V, TMP

       C = 0.000018;
       R = 8100.0;
       E = 20.0;
       T = 0.31;
       TMP = ERCT (T, R, C)
       PRINT '(a,F7.2)',' ERCT (T, R, C): ', TMP
       V = VCAP (E, T, R, C)
       PRINT '(a,F7.2)',' VCAP (E, T, R, C): ', V

       END

The D main program:
import std.stdio;

// mathproc.dll subroutine declarations
extern (Pascal)
{
	float ERCT (ref float, ref float, ref float);
	float VCAP (ref float, ref float, ref float, ref float);
}

int main(string[] args)
{
	float C, R, t, E, L, V, I, tmp;

	C = 0.000018;
	R = 8100.0;
	E = 20.0;
	t = 0.31;
	tmp = ERCT (C,R,t);
	printf ("  ERCT (C,R,t): %f \n", tmp);
	V = VCAP(C,R,t,E);
	printf ("  VCAP(C,R,t,E): %f \n", V);
	return (0);
}

[extern (Pascal) requires the parameters passed in reverse order]

Have successfully called other float/REAL*4 FORTRAN functions 
from both
D command line and Windows programs (please see
http://rrroberts.50webs.com/cobindex.htm#DCALLS for example 
links; please see 
http://rrroberts.atwebpages.com/stf95cob.htm#DATAEQV for the 
Application Binary Interface).

It was suggested to load salflibc.dll (think of it as SilverFrost 
run-time library) at the start; so added
LoadLibraryA ("C:\\Program Files\\Silverfrost\\FTN95 
Express\\salflibc.dll");
immediately after the data declaration.  No change.

When dmath.exe profiled with Dependency Walker, noticed many 
calls to DllMain (yes, familiar with D's DllMain in user-written 
D .dlls; Silverfrost FTN95 uses LibMain).  Also, received the 
following error:
Second chance exception 0xC0000090 (Float Invalid Operation) 
occurred in "SALFLIBC.DLL" at address 0x0053EB0A.

It appears that using a D main program to call ERCT (C,R,t) in 
user-written mathproc.dll, which in turn calls functions in the 
Silverfrost salflibc.dll, causes something to "stepped on" on the 
FORTRAN side.  This issue also applies to SINH(), COSH(), TANH().

Have been toying with idea of using Sliverfrost C compiler to add 
a DllMain to mathproc.dll, though not sure what that would 
accomplish.

Any suggestions will be greatly appreciated.

Thanks.
Nov 15 2014
parent "Kagamin" <spam here.lot> writes:
Well, the easiest thing is to see assembler generated at both 
sides and check if they are compatible. If they are not, try to 
interface via C ABI. You can also inspect value of X before 
calling EXP.
Nov 16 2014