- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Is there any way to tell the compiler to ignore the DLLEXPORT directive during compilation?
John.
Is there any way to tell the compiler to ignore the DLLEXPORT directive during compilation?
John.
Link Copied
14 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Not a direct answer to your question, but these days I prefer to get rid of all DLLEXPORT attributes and export the symbols through a .def file, like:
The .def file can be simply included in your project, and it's automatically given to the linker. That approach centralizes the export control and reduces "pollution" of the source code.
LIBRARY MyDll.dll
EXPORTS
subroutine1
subroutine2
subroutine3 = _subroutine3@24 (in the case of stdcall symbol)
The .def file can be simply included in your project, and it's automatically given to the linker. That approach centralizes the export control and reduces "pollution" of the source code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Using a .DEF file when exporting routines is fine. I would not do it for data, as the compiler often needs to know that a data object has been exported. When importing data objects, a DLLIMPORT directive is required.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A .DEF file is not an option for me, since the dll's I create export procedures as well as data.
The reason I asked is because when trying to create a static version of a library with the same code used for the dll, the compiler seems keeps the dll-naming conventions and as a result, any program that makes use of the static library cannot be compiled/linked again (there are always unresolved externals).
But anyway, thanks for the reply.
John.
The reason I asked is because when trying to create a static version of a library with the same code used for the dll, the compiler seems keeps the dll-naming conventions and as a result, any program that makes use of the static library cannot be compiled/linked again (there are always unresolved externals).
But anyway, thanks for the reply.
John.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I just remembered that I have another question to ask (since the last one, it seems, can only be solved with the DEC$IF DEFINED) though it's not related to the title of the post, it's rather an standards-related question.
When I add the BIND(C, NAME='whatever') to an ELEMENTAL procedure, I always get an error ---I know that there are no ELEMENTAL procedures in C, but what if I intend to use those procedures in Fortran executables as well? Does that mean that the BIND attribute implies that the code shouldn't be used from Fortran? Thanks.
John.
When I add the BIND(C, NAME='whatever') to an ELEMENTAL procedure, I always get an error ---I know that there are no ELEMENTAL procedures in C, but what if I intend to use those procedures in Fortran executables as well? Does that mean that the BIND attribute implies that the code shouldn't be used from Fortran? Thanks.
John.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
BIND(C) means that the routine (or whatever) is "interoperable" with C. That does not mean it can't be used from Fortran too. There are some restrictions on BIND(C) and I'll look at this some more on Monday.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the reply!
My "default" logic was to think of BIND(C) as a substitute for the DEC$'s C/STDCALL directives and all that they involve, but the error thrown by the compiler made me think that maybe the F2003 standard suggested that the "interoperable" code *shouldn't* be used from Fortran ---one hint to that is the fact that ENUM is defined only in terms of interoperability with C, and not as a regular Fortran statement; the other is the fact that, according to the /stand:f03 warnings, the standard expects only single-byte character arguments in interoperable procedures (and in that case, I might pass the ASCII integer instead).
This might be off-topic, but: The Fortran standard is good at reminding me some lines said by Al Pacino in The Devil's Advocate movie (Look but don't touch. Touch, but don't taste. Taste, don't swallow)... In this case the F2003 standards' sentence would be "We have pointers, but don't use them. OK, use them but not as arguments. OK, use them as arguments, but not with INTENT..."
It seems to me that there is always a *but* in the way things are expected to work. And, yes, it could have been worser (e.g., like moving from VB6 to VB.NET), but it's still too rigid to be portable.
I solved the problem by using a wrapper to the ELEMENTAL procedure ---and it seems that the PURE attribute doesn't conflict with BIND(C).
John.
My "default" logic was to think of BIND(C) as a substitute for the DEC$'s C/STDCALL directives and all that they involve, but the error thrown by the compiler made me think that maybe the F2003 standard suggested that the "interoperable" code *shouldn't* be used from Fortran ---one hint to that is the fact that ENUM is defined only in terms of interoperability with C, and not as a regular Fortran statement; the other is the fact that, according to the /stand:f03 warnings, the standard expects only single-byte character arguments in interoperable procedures (and in that case, I might pass the ASCII integer instead).
This might be off-topic, but: The Fortran standard is good at reminding me some lines said by Al Pacino in The Devil's Advocate movie (Look but don't touch. Touch, but don't taste. Taste, don't swallow)... In this case the F2003 standards' sentence would be "We have pointers, but don't use them. OK, use them but not as arguments. OK, use them as arguments, but not with INTENT..."
It seems to me that there is always a *but* in the way things are expected to work. And, yes, it could have been worser (e.g., like moving from VB6 to VB.NET), but it's still too rigid to be portable.
I solved the problem by using a wrapper to the ELEMENTAL procedure ---and it seems that the PURE attribute doesn't conflict with BIND(C).
John.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sure enough, the standard prohibits the use of a BIND with ELEMENTAL. Offhand I can't think of a rationale for that, since at heart an ELEMENTAL procedure is one that acccepts and returns scalars. Maybe the committee figured that the "elemental-ness" of it didn't translate to C and therefore it would be not interoperable.
In general, yes, BIND(C) is an adequate replacement for non-standard syntax such as !DEC$ ATTRIBUTES, though be careful since BIND(C) does not imply pass-by-value! I would not let this little irritation prevent you from using BIND(C) - creating an ELEMENTAL jacket seems like a good idea.
In general, yes, BIND(C) is an adequate replacement for non-standard syntax such as !DEC$ ATTRIBUTES, though be careful since BIND(C) does not imply pass-by-value! I would not let this little irritation prevent you from using BIND(C) - creating an ELEMENTAL jacket seems like a good idea.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jugoslav,
What would my .def file look like for these export statements?
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, ALIAS:'EtOHLiqDens_F' :: EtOHLiqDens_F
!DEC$ ATTRIBUTES REFERENCE :: TempC, Value, Units
Thanks,
David
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
David, there are multiple choices; here's one:
code:
.def file
That will export both "EtOHLiqDens_F" and "_etohliqdens_f@12" (in case you need the latter), referencing the same subroutine. (Note that STDCALL implies lowercase name decoration. -- you can achieve similar effect by compiler switches in "External procedures/Calling convention" )
I noticed that in IVF, .def file is not automatically recognized when added to the project. You will also have to add /DEF:dll1.def to Project properties/Linker/Command line.
code:
subroutine EtOHLiqDens_F(TempC, Value, Units)
!DEC$ ATTRIBUTES STDCALL, REFERENCE :: EtOHLiqDens_F
real:: TempC, Value, Units
...
end subroutine
.def file
LIBRARY Dll1.dll
EXPORTS
EtOHLiqDens_F=_etohliqdens_f@12
_etohliqdens_f@12
That will export both "EtOHLiqDens_F" and "_etohliqdens_f@12" (in case you need the latter), referencing the same subroutine. (Note that STDCALL implies lowercase name decoration. -- you can achieve similar effect by compiler switches in "External procedures/Calling convention" )
I noticed that in IVF, .def file is not automatically recognized when added to the project. You will also have to add /DEF:dll1.def to Project properties/Linker/Command line.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jugoslav,
My actual variable declarations are
Real
(KIND=8), INTENT(IN) :: TempCReal
(KIND=8), INTENT(OUT) :: ValueCharacter(LEN=20), INTENT(OUT) :: Units
Can this be handled OK with what you suggested? I guess the length would be @36 instead of @12.
Thanks,
David
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, whatever the size of a variable is, the REFERENCE will cause only the pointer to it to be passed, yielding @4 for each.
By default, character arguments will require additional passing of character variable length (giving additional @4 for each, by default passed at the end of arg-list), unless both STDCALL or C is specified for the routine and REFERENCE spelled out for the character argument. If you're calling that from another language .exe, you may want to suppress that and pass the length explicitly.
Please take a thorough read of both "Attributes REFERENCE and VALUE" and "Attributes C and STDCALL" in the man pages. The interaction of those attributes is very convoluted and occasionally counterituitive (heritage from MS PowerStation). Here's a couple of examples of matching C and Fortran signatures:
By default, character arguments will require additional passing of character variable length (giving additional @4 for each, by default passed at the end of arg-list), unless both STDCALL or C is specified for the routine and REFERENCE spelled out for the character argument. If you're calling that from another language .exe, you may want to suppress that and pass the length explicitly.
Please take a thorough read of both "Attributes REFERENCE and VALUE" and "Attributes C and STDCALL" in the man pages. The interaction of those attributes is very convoluted and occasionally counterituitive (heritage from MS PowerStation). Here's a couple of examples of matching C and Fortran signatures:
void __stdcall foo(double&, double&, char*, int)
subroutine FOO(Real81, Real82, String) !_foo@16
!DEC$ATTRIBUTES STDCALL, REFERENCE:: Foo
...character(*) String
void __stdcall foo(double&, double&, char*) !_foo@12
subroutine FOO(Real81, Real82, String)
!DEC$ATTRIBUTES STDCALL, REFERENCE:: Foo
!DEC$ATTRIBUTES REFERENCE:: String
...character(42) String !Requires hard-coded length, as it's not passed
void __stdcall foo(double&, double&, char*, int&)
subroutine FOO(Real81, Real82, String, Len) !_foo@16
!DEC$ATTRIBUTES REFERENCE:: String
!DEC$ATTRIBUTES STDCALL, REFERENCE:: Foo
character(Len) String
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jugoslav, can we go back to your original comment which prompted me to join this thread ...
" I prefer to get rid of all DLLEXPORT attributes and export the symbols through a .def file".
We seem to have moved along way from there. I am calling a Fortan DLL from Excel VBA using the DEC$ Directives shown. As I have some 80 routines, I get 160 warning messages when compiling.
I was hoping to avoid these by using a .DEF file. I'm no longer clear that this is realisitically possible for my scenario. In which case, I'll just have to put up with the messages, or do you have a way to do this?
Thanks, David
" I prefer to get rid of all DLLEXPORT attributes and export the symbols through a .def file".
We seem to have moved along way from there. I am calling a Fortan DLL from Excel VBA using the DEC$ Directives shown. As I have some 80 routines, I get 160 warning messages when compiling.
I was hoping to avoid these by using a .DEF file. I'm no longer clear that this is realisitically possible for my scenario. In which case, I'll just have to put up with the messages, or do you have a way to do this?
Thanks, David
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
160 warnings for what? F9x Standard violations? Yes, that can be annoying.
Like I said, you can avoid !DEC$ATTRIBUTES by compiling the entire dll with adjusted settings in Properties/Fortran/Calling conventions (e.g. STDCALL/REFERENCE + lowercase names). However, if the dll uses other .libs and/or .dlls, they have to be rebuilt too.
As for the string arguments, you can't get rid of the hidden length passing by means of compiler switches -- either keep the REFERENCE for those, or pass the buffer length (it's a good idea anyway) from the VB as a ByVal int (long?), like in my first example above.
VF10 brings the F2003 BIND(C) attribute, but as far as I can tell you can't specify STDCALL in there. I recall a suggestion on c.l.f. to enhance the syntax like BIND(C, STDCALL, NAME="Whatever")
P.S. Steve, I'm not sure if printing F2003 features in cyan in the Compiler Documentation was a good idea -- in this way, they're equated with VF extensions, which they're not really.
P.P.S. Steve, is /Qdiag-disable something new in VF10? If so, where can I find the list of message IDs referred to therein?
Like I said, you can avoid !DEC$ATTRIBUTES by compiling the entire dll with adjusted settings in Properties/Fortran/Calling conventions (e.g. STDCALL/REFERENCE + lowercase names). However, if the dll uses other .libs and/or .dlls, they have to be rebuilt too.
As for the string arguments, you can't get rid of the hidden length passing by means of compiler switches -- either keep the REFERENCE for those, or pass the buffer length (it's a good idea anyway) from the VB as a ByVal int (long?), like in my first example above.
VF10 brings the F2003 BIND(C) attribute, but as far as I can tell you can't specify STDCALL in there. I recall a suggestion on c.l.f. to enhance the syntax like BIND(C, STDCALL, NAME="Whatever")
P.S. Steve, I'm not sure if printing F2003 features in cyan in the Compiler Documentation was a good idea -- in this way, they're equated with VF extensions, which they're not really.
P.P.S. Steve, is /Qdiag-disable something new in VF10? If so, where can I find the list of message IDs referred to therein?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Regarding Jugoslav's PS and PPS. 1) We made an explicit decision to treat the F2003 features as extensions as we claim to be an F95 compiler and the black text reflects F95. We plan to switch to black text for F2003 in a future release.
/Qdiag-disable is new in 10.0, but most of the compiler messages are not tied in to the message ID scheme yet. That's something we're working toward. If a message comes out with a numeric ID, then you can disable it, otherwise not. The Static Verifier messages all have IDs, for example.
Oh, and we're not going to extend BIND with STDCALL. Since that would be an extension, you'd just be trading one for another and you'd still get the diagnostic.
/Qdiag-disable is new in 10.0, but most of the compiler messages are not tied in to the message ID scheme yet. That's something we're working toward. If a message comes out with a numeric ID, then you can disable it, otherwise not. The Static Verifier messages all have IDs, for example.
Oh, and we're not going to extend BIND with STDCALL. Since that would be an extension, you'd just be trading one for another and you'd still get the diagnostic.

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