- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
Link Copied
7 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Steve
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The simplest way is to do something like:
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)
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)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
or
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please submit this to vf-support@compaq.com - to be honest, I didn't even know that feature was in there!
Steve
Steve
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page