- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello:
I've got this .DLL written by someone else that I need to call from my Fortran program. It is either C or C++, not sure.
None of the examples in the compiler documentation cover this combination.
My old compiler used the following statement (along with a compiler directive
to use Microsoft Mixed language name decoration) to pass the variable "TString"
to/from the .DLL and it worked fine:
dll_import TString
So, with the Intel compiler, I found the following suggestion in the knowledge database:
!DEC$ ATTRIBUTES DLLIMPORT, ALIAS: 'TString' ::TString
if I try that, I get an unsatisfied external error message, saying the the linker cannotresolve __imp_Tstring
If I try
!DEC$ ATTRIBUTES DLLIMPORT, ALIAS: 'TString' ::__imp_TString
the unsatisfied external error reference changes to _TSTRING
Trying
!DEC$ ATTRIBUTES DLLIMPORT, ALIAS: 'TString' ::__imp_TSTRING
makes no difference.
I have put copies of the .DLL in the directory where the object and .EXE files
reside and in the directory where the source files reside without success.
So, now I`ve run out of ideas.
Does anyone have any
Thanks
I've got this .DLL written by someone else that I need to call from my Fortran program. It is either C or C++, not sure.
None of the examples in the compiler documentation cover this combination.
My old compiler used the following statement (along with a compiler directive
to use Microsoft Mixed language name decoration) to pass the variable "TString"
to/from the .DLL and it worked fine:
dll_import TString
So, with the Intel compiler, I found the following suggestion in the knowledge database:
!DEC$ ATTRIBUTES DLLIMPORT, ALIAS: 'TString' ::TString
if I try that, I get an unsatisfied external error message, saying the the linker cannotresolve __imp_Tstring
If I try
!DEC$ ATTRIBUTES DLLIMPORT, ALIAS: 'TString' ::__imp_TString
the unsatisfied external error reference changes to _TSTRING
Trying
!DEC$ ATTRIBUTES DLLIMPORT, ALIAS: 'TString' ::__imp_TSTRING
makes no difference.
I have put copies of the .DLL in the directory where the object and .EXE files
reside and in the directory where the source files reside without success.
So, now I`ve run out of ideas.
Does anyone have any
Thanks
Link Copied
10 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
you may need to add the STDCALL attribute to your declaration to allow for the differences between C and Fortran.
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, ALIAS: 'TString' ::TString
David
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, ALIAS: 'TString' ::TString
David
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Use DUMPBIN on your C DLL to see what the actual symbol used for your routine/function Tstring. It may or may not have a leading underscore or trailing '@n' where 'n' is an integer equal to 4 times the number of arguments. It may be mixed case ('TString') or uppercase ('TSTRING'). In the worst case, if the C DLL was not compiled with declarations using 'extern "C" then the DLL symbols will be a 'mangled' as well. You have to get the alias exactly right to match what is in the DLL's symbol table.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A couple of problems here.
First, do not use "__imp_" in your code. This string is added by the linker for DLLIMPORTed symbols. So your first line:
!DEC$ ATTRIBUTES DLLIMPORT, ALIAS: 'TString' ::TString
is almost correct. I would change this to:
!DEC$ ATTRIBUTES DLLIMPORT, DECORATE, ALIAS: 'TString' ::TString
Omitting DECORATE will prevent the leading underscore from being added on IA-32.
Second, the DLL is not involved in the build process. You want instead to add the .LIB, that was created when the DLL was built, to your project or to Additional Dependencies under Linker properties.
You can use "dumpbin -exports" on the .LIB to see what symbols it exports.
First, do not use "__imp_" in your code. This string is added by the linker for DLLIMPORTed symbols. So your first line:
!DEC$ ATTRIBUTES DLLIMPORT, ALIAS: 'TString' ::TString
is almost correct. I would change this to:
!DEC$ ATTRIBUTES DLLIMPORT, DECORATE, ALIAS: 'TString' ::TString
Omitting DECORATE will prevent the leading underscore from being added on IA-32.
Second, the DLL is not involved in the build process. You want instead to add the .LIB, that was created when the DLL was built, to your project or to Additional Dependencies under Linker properties.
You can use "dumpbin -exports" on the .LIB to see what symbols it exports.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, but none of these suggestions work.
First of all, it's been so long since I recompiled my program that I forgot
that I needed the .LIB files.
Once I looked at those I found that the variable being exported is named:
_TString@12
In my program, it is an integer function with three arguments, so the '@12' suffix makes sense.
The old calling sequence is
integer=TSTRING(A,B, Val(n))
where A and B are strings and Val is a non-standard feature of the old
compiler (call by value). I presume the Intel compiler has an equivalent somewhere.
I removed the "Val" for the moment and changed
integer(kind=4) :: TString
to
integer(kind=4), external :: TString
(otherwise DECORATE won't work)
and tried every combination of the ATTRIBUTES properties that I could think of.
One possibility is
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, DECORATE :: TString
which gives an error saying that __imp__tstring@12 is an unsatisfied external.
Leaving out the STDCALL changes the case and removes the suffix so that
the unsatisfied external becomes __imp__TSTRING
If I use ALIAS, it seems to negate the DECORATE keyword.
!DEC$ ATTRIBUTES DLLIMPORT, DECORATE, ALIAS : 'TString' :: TString
and the unsatisfied external becomes __imp__TString
Adding STDCALL to this does nothing.
The closest I could come was the following:
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, DECORATE , ALIAS : 'TString@12' :: TString
which gives the error
unresolved external symbol __imp__TString@12 referenced
At least the case is now correct, as is the suffix. Now, how do I get rid of
the "__imp__" or the excess underscores if the linker is really adding "_imp_" ?
Thanks for any suggestions.
First of all, it's been so long since I recompiled my program that I forgot
that I needed the .LIB files.
Once I looked at those I found that the variable being exported is named:
_TString@12
In my program, it is an integer function with three arguments, so the '@12' suffix makes sense.
The old calling sequence is
integer=TSTRING(A,B, Val(n))
where A and B are strings and Val is a non-standard feature of the old
compiler (call by value). I presume the Intel compiler has an equivalent somewhere.
I removed the "Val" for the moment and changed
integer(kind=4) :: TString
to
integer(kind=4), external :: TString
(otherwise DECORATE won't work)
and tried every combination of the ATTRIBUTES properties that I could think of.
One possibility is
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, DECORATE :: TString
which gives an error saying that __imp__tstring@12 is an unsatisfied external.
Leaving out the STDCALL changes the case and removes the suffix so that
the unsatisfied external becomes __imp__TSTRING
If I use ALIAS, it seems to negate the DECORATE keyword.
!DEC$ ATTRIBUTES DLLIMPORT, DECORATE, ALIAS : 'TString' :: TString
and the unsatisfied external becomes __imp__TString
Adding STDCALL to this does nothing.
The closest I could come was the following:
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, DECORATE , ALIAS : 'TString@12' :: TString
which gives the error
unresolved external symbol __imp__TString@12 referenced
At least the case is now correct, as is the suffix. Now, how do I get rid of
the "__imp__" or the excess underscores if the linker is really adding "_imp_" ?
Thanks for any suggestions.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
With reference to my previous posting and if anyone else needs to know, the final try:
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, DECORATE , ALIAS : 'TString@12' :: TString
seems to work - at least it linked OK !!
I had the linker LIBPATH set incorrectly.
Now, does anyone know a quick answer to the following:
How do you pass 3 variables to a C routine when the first two are by reference, and the last one is by value?
The ATTRIBUTES syntax doesn't seem to allow mixed references.
Thanks
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, DECORATE , ALIAS : 'TString@12' :: TString
seems to work - at least it linked OK !!
I had the linker LIBPATH set incorrectly.
Now, does anyone know a quick answer to the following:
How do you pass 3 variables to a C routine when the first two are by reference, and the last one is by value?
The ATTRIBUTES syntax doesn't seem to allow mixed references.
Thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Oh, you had confused as all:
"Once I looked at those I found that the variable being exported is named:
_TString@12
In my program, it is an integer function with three arguments"
Variable is not a Function. Those are two distinct categories: you use variables, but you call functions (and subroutines, generally referred to as procedures). From the start, we thought that TString is a variable, but it was a procedure all the way.
Now, with that cleared up: your solution works, but it is not exactly nice.
All the time, the problem was that the compiler could not figure out the "@12" part (meaning, there are 12/4 = 3 arguments to the function). When it "sees" the call integer=TSTRING(A,B, Val(n)), it's too late, because you had to tell it ALIAS beforehand.
The straightforward solution is to tell the compiler in advance about the prototype of the function: you should put an INTERFACE block somewhere in the declaration part, like:
"Once I looked at those I found that the variable being exported is named:
_TString@12
In my program, it is an integer function with three arguments"
Variable is not a Function. Those are two distinct categories: you use variables, but you call functions (and subroutines, generally referred to as procedures). From the start, we thought that TString is a variable, but it was a procedure all the way.
Now, with that cleared up: your solution works, but it is not exactly nice.
All the time, the problem was that the compiler could not figure out the "@12" part (meaning, there are 12/4 = 3 arguments to the function). When it "sees" the call integer=TSTRING(A,B, Val(n)), it's too late, because you had to tell it ALIAS beforehand.
The straightforward solution is to tell the compiler in advance about the prototype of the function: you should put an INTERFACE block somewhere in the declaration part, like:
[fortran]INTERFACE INTEGER FUNCTION TString(A, B, N) !DEC$ATTRIBUTES STDCALL, REFERENCE, DECORATE, ALIAS: "TString":: TString !Correct the following, I made a guess: REAL:: A REAL:: B !DEC$ATTRIBUTES VALUE:: N INTEGER:: N END FUNCTION END INTERFACE[/fortran]That should also answer your last question: REFERENCE attribute specifies that reference is the default, but VALUE for N overrides it. You call it just like
[bash]i = TString(x, y, i)[/bash]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting YertleTheTurtle
With reference to my previous posting and if anyone else needs to know, the final try:
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, DECORATE , ALIAS : 'TString@12' :: TString
seems to work - at least it linked OK !!
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, DECORATE , ALIAS : 'TString@12' :: TString
seems to work - at least it linked OK !!
That would be incorrect - the alias string should be 'TString'. DECORATE will add the @12 and the leading underscore.
You can specify VALUE or REFERENCE as an attribute on individual arguments.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi:
I tried those solutions, and they worked in combination.
Thank you all.
A couple of questions, just to clarify my understanding:
1. Why must the statement
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, reference, DECORATE, ALIAS: "TString":: TString
ONLY appear once, and ONLY in the interface block? If it appears twice, once in the INTERFACE and once in the actual subroutine that calls TString, you get an inscrutable Fortran error message as follows:
"The attributes of this name conflict with those made accessible by a USE statement"
even if both ATTRIBUTES statements are identical.
2. What does !DEC$ stand for? Is this a reference to some ancient DEC compiler extension?
Again, thanks.
Yert
I tried those solutions, and they worked in combination.
Thank you all.
A couple of questions, just to clarify my understanding:
1. Why must the statement
!DEC$ ATTRIBUTES DLLIMPORT, STDCALL, reference, DECORATE, ALIAS: "TString":: TString
ONLY appear once, and ONLY in the interface block? If it appears twice, once in the INTERFACE and once in the actual subroutine that calls TString, you get an inscrutable Fortran error message as follows:
"The attributes of this name conflict with those made accessible by a USE statement"
even if both ATTRIBUTES statements are identical.
2. What does !DEC$ stand for? Is this a reference to some ancient DEC compiler extension?
Again, thanks.
Yert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
1) You did not show us the code, but as I get it, you have the INTERFACE in a MODULE, and then you again declare the attributes in the subroutine that USEs that module? The Fortran philosophy is, simply, that you may not redeclare things (although there are exceptions that can get really complicated), even if they are identical. I find it simple and straightforward enough.
2) Yes, !DEC$ originally stands for that DEC, because it is a significant part of Intel Fortran heritage, and the extension indeed draws from these days. When Intel acquired Compaq Fortran (which acquired Digital/DEC around 1998), they invented a backronym "Directive Enhanced Compilation" for it, but it did not really caught on (not that they pushed it very hard).
2) Yes, !DEC$ originally stands for that DEC, because it is a significant part of Intel Fortran heritage, and the extension indeed draws from these days. When Intel acquired Compaq Fortran (which acquired Digital/DEC around 1998), they invented a backronym "Directive Enhanced Compilation" for it, but it did not really caught on (not that they pushed it very hard).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
We invented the "backronym" just to placate a few in management who questioned it. It worked. We all know what it really means...
But if it bothers you, you can use !DIR$ instead.
But if it bothers you, you can use !DIR$ instead.

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