Software Archive
Read-only legacy content
17060 Discussions

STD Call/Module annoyance

Dalziel__Stuart
Beginner
1,004 Views
I've just installed the v6.6a patch and have come across a small annoyance with a change in the way it handles modules.

With v6.6 and earlier, the following code would work:

module ToCall

interface myFunction
module procedure myFunction
end interface

contains

function myFunction(a,b,c,d)
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_myFunction@16' :: myFunction
...
myFunction = Whatever
end function
end module

module MakeCall
use ToCall
contains

subroutine Test()
...
ret = myFunction(v,x,y,z)
...
end subroutine

end module

However, the new version of the compile complains about the function myFunction being an externally defined symbol due to having both a module interface and attributes command.

The work around is to (a) remove the module procedure interface statement, and (b) add a second attributes command in the MakeCall module.

It was much tidier when those details could be passed via the modules.

As an aside, I have noticed a decrease in compilation speed for my top-most modules that are using lots of other modules.

Regards,

Stuart.
0 Kudos
7 Replies
Steven_L_Intel1
Employee
1,004 Views
Well, the compiler is right to complain. What more can I say?

Steve
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,004 Views
I feel new behaviour of the compiler is right in this particular case; I don't know what the standard exactly says (but !DEC$ATTRIBUTES is an extension anyway), but lines
interface myFunction  
   module procedure myFunction  
end interface 

a) do nothing b) I'm not sure if it's even allowed by the standard c) lead to an ambiguity when you specify ATTRIBUTES (as you can see). Named INTERFACE is necessary only when you want to rename something or give same name to several routines.

Jugoslav
0 Kudos
Steven_L_Intel1
Employee
1,004 Views
To expand on what Jugoslav said, a CONTAINed module procedure is its own interface - you don't need, and are not allowed to specify, an INTERFACE for it.

Steve
0 Kudos
Dalziel__Stuart
Beginner
1,004 Views
Unfortunately, my original message lost some linebreaks between submission (and the e-mailed copy I received) and appearing on the forum.

As a consequence, the responders (thanks anyway) appear to have overlooked a critical "end module". To overcome this I repeat the code below with what I hope is a surplus of blank lines to avoid the problem:

module ToCall

interface myFunction

module procedure myFunction

end interface

contains

function myFunction(a,b,c,d)

!DEC$ ATTRIBUTES STDCALL, ALIAS : '_myFunction@16' :: myFunction

...

myFunction = Whatever

end function

! Note that this is the end of the first module!

end module

module MakeCall

use ToCall

contains

subroutine Test()

...

ret = myFunction(v,x,y,z)

...

end subroutine

end module

Note that one module is NOT contained within the other. Indeed, they are in separate files, and sometimes have a number of other intermediate modules.

I accept the comment that a named interface statement is not essential, but it makes the structure of my macro for automatically creating interface statements (including generic interfaces -- see below) somewhat simpler, and does not do any harm (removing it does not change the issue).

To clarify the situation further, the real MyFunction(..) procedures are Win32 callback procedures (hence the STDCALL and ALIAS), but I also need to call them directly from other, higher-level modules, hence the desirability of having them as a module procedure. I would have thought, naievely, that specification of the calling convenction would be possible for a module procedure...

On the subject of automatic generation of the interface statements (a pain if you have to do it manually), I have adopted a naming convention whereby if the specific name contains a $ symbol, then the $ and everything after it are discarded to create the interface statement. If the name starts with a $, then it is marked as private (but may still be generic if there is a second $ later in the name). By running a simple macro in my favourite editor, I can automatically generate a new interface statement when I change or add bits to a file, without getting to compile time to discover that I have missed or mistyped the name of a new routine.

I must admit that it would be great if the Fortran standard could be extended so that we could make a routine generic by including (one or more) simple 'generic MyName' statements within the routine

It would also be useful if a symbol imported from a module (or an entire used module) could be made private without having to first make everything private. (I used to do the latter, but discovered somewhere during v5 that you cannot have two public statements for the same symbol, the work around for which would have made my interface extraction macro much more complex, but that is another story...)

Stuart
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,004 Views
Huh... lot of things to respond to. First, we (OK, at least I) didn't overlook END MODULE. Second, you can have !DEC$ATTRIBUTES for module routines, and they'll be called correctly by either Win32 as callback or for your other routines only provided they USE the module. The problem was, the compiler thought you're trying to apply !DEC$ATTRIBUTES to generic myFunction (i.e. the one in INTERFACE myFunction, which is obviously silly) rather to overloaded myFunction (i.e. the one whose body is in a module). My comments that i'm suspicious as to standard-conformity of the INTERFACE block is that it's strange indeed having myFunction renamed to myFunction (and the obvious ambiguity had hit you). You never need INTERFACE blocks for module procedures (and as Steve pointed, sometimes it's even illegal); the only exception is when you are referring to more than one function to be available under same name but different arguments.

Jugoslav
0 Kudos
Dalziel__Stuart
Beginner
1,004 Views
Mmmm...

Having now actually tried to compile my example, it becomes clear that the problem must be elsewhere. Apologies for constructing an example without actually testing it.

There is a problem somewhere in my proper such that unless I have the second ATTRIBUTES statement where the function is called under v6.6a then I get a link-time error (no INTERFACE statement) about not finding the function.

Any suggestions? Note the error is link-time, not compile time, so it appears that the compiler is finding the name within the module, but not the ATTRIBUTE information.

My (over) simplified sample code reflects the structure, but in retrospect it does not recreate the problem.

Things worked for previous versions (i.e. up to and including v6.6) with the INTERFACE statement - they may also have worked without it...

Thanks for the comments to date!

Stuart.
0 Kudos
Steven_L_Intel1
Employee
1,004 Views
I suggest sending an example that DOES recreate the problem to us at vf-support@compaq.com. We'll be glad to look into it.

Steve
0 Kudos
Reply