Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29277 Discussions

Floating point control problem when call fortran dll from R

axm
Beginner
2,107 Views
Hey guys, I encountered some problems when I tried to call fortran dll from R, a statistical package. my fortran dll is compiled based on intel fortran 10.x for window, MS visual studio 2005, and IMSL 6.0. when I try to load the dll into R, R report a warnming message "DLL attempted to change FPU control word from 8001f to 9001f". I just googled this problem, and a solution given by Duncan Murdoch @ http://www.stats.uwo.ca/faculty/murdoch/software/compilingDLLs/#fpu
is as follows
"

R sets the floating point control word using the R.dll function Rwin_fpset. This sets the FPU to mask all exceptions, use 64 bit precision, and round to nearest or even.

R expects all calls to DLLs (including the initializing call) to leave the FPU control word unchanged. Many run-time libraries reset the FPU control word during initialization; this will cause problems in R, and will result in a warning message like "DLL attempted to change FPU control word from 8001f to 9001f". The value 8001f that gets reported is in the format expected by the C library routine _controlfp; the raw value that is used in the FPU register is 037F.

If you can't tell your compiler to generate a DLL that leaves the FPU alone, then you need to be sure to restore it to R's value before returning to R. See the Delphi section for an example of how to do this in that language. "

However, I do not quite follow his method. It seems that the best way is to tell intel fortran to generate a DLL that leaves the FPU alone. How can I do that then? Thanks a lot!

0 Kudos
16 Replies
Steven_L_Intel1
Employee
2,107 Views
To the best of my knowledge, there's no code added by the Fortran compiler to change the FP status registers except in a main program. I make no promises about IMSL. It would be worth creating a test case that did not call IMSL to test that.

I suppose you could call FOR_GET_FPE at the entry to your DLL, save the value, then call FOR_SET_FPE with that value before returning. That may do the trick. Both of these are documented in the Language Reference.
0 Kudos
TimP
Honored Contributor III
2,107 Views
Intel Fortran should make permanent changes to FPU control word only in a main program, which are done in accordance with Microsoft practice (53-bit precision, for 32-bit mode). I suspect you would have to reset the value explicitly, if you have a Fortran main program. Among the methods for doing that would be C functions which use _controlfp(). I don't know whether the CVF methods for controlling it are still available.
If you are concerned also about the SSE control, the option /Qftz- (when compiling a Fortran main program) will leave gradual underflow set.
0 Kudos
axm
Beginner
2,107 Views
Hi Steve, Thanks for your suggestion. I just remove the IMSL function from my testing code, and R do not report warning anymore, but it can still not load the fortran function into R successfully. on the same website I mentioned before they also mentioned this problem as follows
"

is.loaded() returning FALSE

When R uses dyn.load() to load a DLL, it relies on the DLL's export table to find functions. Many compilers use fairly obscure methods to get a function name into the export table. If you don't follow them exactly, your function won't be available to R.

Some compilers (e.g. g77, as mentioned above) make changes to the function names before putting them in the export table. If you specify the original name, R may not be able to find the entry point."

do you know how intel fortran get a function name into the export table? Thanks!
0 Kudos
TimP
Honored Contributor III
2,107 Views
If you mean the external name of the function, the default for Intel Fortran windows is all uppercase identifier, with no appended underscores. It's controlled by the options /Quppercase or lowercase, and /us. Also, it may be controlled by $DEC directives or iso_c_binding.
0 Kudos
Steven_L_Intel1
Employee
2,107 Views
You need to supply a !DEC$ ATTRIBUTES DLLEXPORT that names the routine. You can optionally use the ALIAS attribute to specify the exact external spelling, otherwise, as Tim notes, you need to know what the conventions are.

There is the notion of a special name for an import library, which is automatically generated by the compiler when you use DLLEXPORT, but that does not apply when doing a dynamic load of the DLL directly, as you are.
0 Kudos
g_f_thomas
Beginner
2,107 Views

Look here

http://www.geocities.com/yongweiwu/stdcall.htm

and see the part about .def which trumps all.

Gerry

0 Kudos
Steven_L_Intel1
Employee
2,107 Views
.def cannot be used when exporting a variable from a DLL (or importing same.) It can be used for routines.
0 Kudos
g_f_thomas
Beginner
2,107 Views

The exports being discussed hereare functions/subroutines from a DLL for which .def's arewell suited, that's why Microsoft introduced them and encourages their use.

Up to your assertion,I've never heard of anyone exporting or importing a variable from a DLL, with or without .def. It's not done. Perhaps you're alluding to 'sharing' data as discussed in a different thread. Piff...

Gerry

0 Kudos
Steven_L_Intel1
Employee
2,107 Views
You may not have heard of it, Gerry, but I can assure you that many of our customers do it based on the questions and issues we get on this topic. While it may not be an issue for the issue in this thread, I mentioned it because .def files are not a panacea. With DLLEXPORTed variables, the compiler needs to add an extra level of indirection to each reference and it can't do that if it doesn't see the directive.
0 Kudos
g_f_thomas
Beginner
2,107 Views

OK, I'll take you at your word.

So show me howto export a variable from a dl, and I don't mean as an argument of an exported procedure. Here's what I'd like to do:

This is thedll,

subroutine Let()

real x

x = 6.

end subroutine Let

I'd like the variable xto be exported by the dll and nothing else. Feel free touse whatever metacommands you deem necessary. When the client loads the dll it should be aware ofthe type and current value of the variable x.

If you like I, as customer. can submit this toPremier Support but I'm sure you'll be able to handle it off the top.

Thanks

Gerry

0 Kudos
Steven_L_Intel1
Employee
2,107 Views
Here's how you have to do it:

module mymod
real x
!dec$ attributes dllexport :: x
contains
subroutine Let ()
!dec$ attributes dllexport :: Let
x = 6
end subroutine Let
end module mymod

Build this into a DLL. Now in your executable project, add:

use mymod

Add to the INCLUDE path of the executable the output directory of the DLL project so that it can see mymod.mod and make the DLL project a dependent of the executable, or add the import library to the executable. Build the executable.

The USE of a module that contains a DLLEXPORT treats it as a DLLIMPORT. The variable and its type will be defined (and the subroutine) as long as you have the USE. I am not sure why you asked for the variable to be exported "and nothing else", though I guess if you are using a .def file you might want to keep that. I'm not sure how .def files mix with DLLIMPORT/EXPORT directives and would suggest you use the directives only.

There is a sample provided, DLLDLL_Shared_Data, which demonstrates this technique.

You can't export a local variable of a subroutine - it has to be something that Fortran considers global. You can also DLLEXPORT a COMMON block.
0 Kudos
g_f_thomas
Beginner
2,107 Views

Thanks, but I knew all that. However, who says the executable is written in Fortran? What now?

Gerry

0 Kudos
Steven_L_Intel1
Employee
2,107 Views
Well, if the executable is not Fortran, then the type information is not available. C++ supports DLLimported variables, but most other languages on Windows (VB to name one) do not. Modular programming would have you write access (get and set) routines (which most any language can deal with) rather than make the variable itself visible. This is an approach I prefer, and it even works with managed code. You can, I suppose, write a routine that returns a pointer to the variable and then you use the language's methods for accessing through pointers, but I consider that ugly (and probably fails with managed code.)
0 Kudos
g_f_thomas
Beginner
2,107 Views

Exactly, that's what I was implying all along. For imported variables, VB6 no, VB.Net, don't know, don't care.

Thanks

Gerry

0 Kudos
Steven_L_Intel1
Employee
2,107 Views
Well, why didn't you say so? This is a Fortran forum, not a VB forum, after all...
0 Kudos
g_f_thomas
Beginner
2,107 Views

You are being rude, but what's new!

I never implied that I was using VB, I don't. FYI, dllexport/import isn't partof C anymore than its a part of Fortran. The OP was clearly interested in Fortran portability, something you failed to appreciate.

Gerry

0 Kudos
Reply