Software Archive
Read-only legacy content
17061 Discussions

!DEC$ ATTRIBUTES in Modules

michael-a-carr
Beginner
998 Views
I am trying to link with an external library. If I write this code, it works just fine:
PROGRAM LINKTEST
!DEC$ ATTRIBUTES STDCALL, ALIAS: '_FMS$_FMSINI' :: FMSINI
IMPLICIT NONE
CALL FMSINI
END PROGRAM

However, if I move the ATTRIBUTES into a module, I get an error on linking:
PROGRAM LINKTEST
USE FMS
IMPLICIT NONE
CALL FMSINI
END PROGRAM
----
MODULE FMS
!DEC$ ATTRIBUTES STDCALL, ALIAS: '_FMS$_FMSINI' :: FMSINI
END MODULE
----
I get this response upon linking:
linktest.obj : error LNK2001: unresolved external symbol _fmsini@0
0 Kudos
7 Replies
Steven_L_Intel1
Employee
998 Views
If you just put the ATTRIBUTES declaration in a module, it has no effect since it is not affecting any declarations in that module. If you create an INTERFACE block in the module for the routine, and put the ATTRIBUTES directive in there, then you'll see the right name show up.

Steve
0 Kudos
michael-a-carr
Beginner
998 Views
Then that leads me to my next question. I am linking to a library that was written for C and expects to receive either a two-dimensional array OR a NULL pointer.

The function would be declared in C as:
void dosomething(double **a);

How can I specify the INTERFACE for this, how would I make the call when I want to send two-dimensional array A, and how would I make the call when I want to send a NULL pointer instead?
0 Kudos
Jugoslav_Dujic
Valued Contributor II
998 Views
The simplest way is to do something like:

 
INTERFACE 
    SUBROUTINE DoSomething(dArray) 
    !DEC$ATTRIBUTES C, ALIAS: '_dosomething':: DoSomething 
    !DEC$ATTRIBUTES VALUE:: dArray 
    INTEGER:: dArray 
    END SUBROUTINE  
END INTERFACE 


When you want to pass an actual array, pass LOC(MyArray).
When you want to pass NULL, pass 0. It could also be realised
using REFERENCE attribute and nullified POINTER, but this
is more complicated.

Jugoslav

p.s. Take care of different treatment of 2-dimensional arrays
in C and Fortran (row-major/column-major)
0 Kudos
michael-a-carr
Beginner
998 Views
Sounds like a good solution, but the problem is that my code must be portable to a non-Compaq compiler. I noticed that LOC() is a Compaq extension to the Fortran specification. Is there a "standard" way to do this so that it is more portable?
0 Kudos
canaimasoft
Beginner
998 Views
Most Fortran 90/95 compilers I'm aware of implement loc(), but as you say, the function is an extension. Considering that calling C functions from Fortran is inherently a non-standard technique I wouldn't worry all that much.

In any case, if you have access to a C compiler, you can implement your own loc():

__stdcall long LOC(long VarAddress)

{

return VarAddress;

};

This should work well with any Fortran compiler that passes arguments by reference (again, __stdcall is another non-standard?)

Best regards,

Marco A. Garcia

Canaima Software

P.O. Box 13162

La Jolla, CA. 92039

U.S.A.

e-mail:mgarcia@canaimasoft.com

Tel/Fax: (619) 233-6831

http://www.canaimasoft.com

Developers of f90SQL the Database Connectivity Solution for Fortran, and f90VB the Library for Fortran-OLE Automation and Fortran-VB Programming
0 Kudos
michael-a-carr
Beginner
998 Views
OK there is a new feature in version 6.5A that looks like it's exactly what I need. Here is a snippet from the online help:



ALLOW_NULL

Enables a corresponding dummy argument to pass a NULL pointer (defined by a zero or the NULL intrinsic) by value for the argument. ALLOW_NULL is only valid if the REFERENCE property is also specified; otherwise, it has no effect.


Now the problem... I tried using this as the following:

 
INTERFACE 
  FUNCTION DOIT(A) 
  COMPLEX(8) :: A(:,:) 
  !DEC$ ATTRIBUTES ALLOW_NULL, REFERENCE :: A 
  END FUNCTION 
END INTERFACE 


From the program I try to call it like this:


CALL DOIT(NULL())


or
 
COMPLEX(8), ALLOCATABLE :: A(:,:) 
  ... 
CALL DOIT(A) 


This looks like it should work, but when I compile I get this error:


"Error: The shape matching rules of actual arguments and dummy arguments have been violated."


Now, it should seem that the ALLOW_NULL would let me give it EITHER an array or a NULL pointer... does it want me to send it an array of NULL pointers? :)


Thanks for your help!

0 Kudos
Steven_L_Intel1
Employee
998 Views
Please submit this to vf-support@compaq.com - to be honest, I didn't even know that feature was in there!

Steve
0 Kudos
Reply