- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a C-code with calls to Fortran subroutines which doesn't work. I wonder if anybody can guess what I'm doing wrong?
The fortran code isdefined as below:
SUBROUTINE FLYCUR2(datafile,grffile)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE :: FLYCUR2
!DEC$ ATTRIBUTES ALIAS: 'FLYCUR2' :: FLYCUR2
CHARACTER*(*) datafile, grffile
...
It's compiled with Intel Fortran compiler v.10 into a dll. I have tested it with a test example written in C# and it works.
The C code is defined as below:
extern int __stdcall FLYCUR2(char *,int,char *,int);
...
FLYCUR2(filename1,n1,filename2,n2);
...
Visual Studio 2008 is used to create a project with theC code. The fortran library (.lib) from the fortrancode is included in "Aditional Depencencies" with the linker.
However when I tried to build the code I get the following error:
Error50error LNK2019: unresolved external symbol __imp__FLYCUR2 referenced in function _print_pages@0GRAFDLL.objGraf_09
Any idea what I'm doing wrong?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, ALIAS: 'FLYCUR2' :: FLYCUR2
!DEC$ ATTRIBUTES REFERENCE :: DATAFILE, GRFFILE
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a C-code with calls to Fortran subroutines which doesn't work. I wonder if anybody can guess what I'm doing wrong?
The fortran code isdefined as below:
SUBROUTINE FLYCUR2(datafile,grffile)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE :: FLYCUR2
!DEC$ ATTRIBUTES ALIAS: 'FLYCUR2' :: FLYCUR2
CHARACTER*(*) datafile, grffile
...
It's compiled with Intel Fortran compiler v.10 into a dll. I have tested it with a test example written in C# and it works.
extern int __stdcall FLYCUR2(char *,int,char *,int);
...
Any idea what I'm doing wrong?
Two things:
- STDCALL attribute causes lowercase name decoration, i.e. "flycur2". You can switch it to uppercase by adding ALIAS attribute, but then also use DECORATE, i.e. !DEC$ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE, DECORATE, ALIAS: "FLYCUR2"
- In Intel fortran, the default passing of string length arguments is at the end of argument-list, i.e. (char*, char*, int, int). (You can get the old, Compaq Visual Fortran behavior, by specifying /iface:cvf switch or /mixed_str_len_arg, but I advise against it). As David said, you can suppress the length passing entirely by specifying !DEC$ATTRIBUTES REFERENCE:: datafile, grffile (but then you must hard-code the length on Fortran side).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, ALIAS: 'FLYCUR2' :: FLYCUR2
!DEC$ ATTRIBUTES REFERENCE :: DATAFILE, GRFFILE
I don't think the problem is in my declaration beacause, as I wrote before, I run the code from C# without any problem. The C# declaration is
[DllImport("sacudll.dll", CallingConvention = CallingConvention.StdCall)]
public static extern long FLYCUR2(String inFile, String outFile);
However I tried the declaration as you proposed and got an error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
extern int __stdcall FLYCUR2(char *,int,char *,int);
...
FLYCUR2(filename1,n1,filename2,n2);
Maybe you should write
i=FLYCUR2(filename1,n1,filename2,n2) ?
In which case it should be defined as an INTEGERFUNCTION on the Fortran side.
On the other hand, if you are defining it as SUBROUTINE on the Fortran side, then you should change the prototype to a VOID function on the C side.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Two things:
- STDCALL attribute causes lowercase name decoration, i.e. "flycur2". You can switch it to uppercase by adding ALIAS attribute, but then also use DECORATE, i.e. !DEC$ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE, DECORATE, ALIAS: "FLYCUR2"
- In Intel fortran, the default passing of string length arguments is at the end of argument-list, i.e. (char*, char*, int, int). (You can get the old, Compaq Visual Fortran behavior, by specifying /iface:cvf switch or /mixed_str_len_arg, but I advise against it). As David said, you can suppress the length passing entirely by specifying !DEC$ATTRIBUTES REFERENCE:: datafile, grffile (but then you must hard-code the length on Fortran side).
1. I tried to call to "flycur2" in the C-code without success.
2. I also tried to arange call parameters as you proposed without success. Further I tested toomit intparameters in the call- no success.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
extern int __stdcall FLYCUR2(char *,int,char *,int);
...
FLYCUR2(filename1,n1,filename2,n2);
Maybe you should write
i=FLYCUR2(filename1,n1,filename2,n2) ?
In which case it should be defined as an INTEGERFUNCTION on the Fortran side.
On the other hand, if you are defining it as SUBROUTINE on the Fortran side, then you should change the prototype to a VOID function on the C side.
I tried with
externvoid __stdcall FLYCUR2(char *,int,char *,int);
but I got the same error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tried with
externvoid __stdcall FLYCUR2(char *,int,char *,int);
but I got the same error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tried with
externvoid __stdcall FLYCUR2(char *,int,char *,int);
but I got the same error.
You seem to have missed my post above. Please read it. (Yes, you do need void as well, but that's a secondary issue.)
edit: ...Oh, and extern "C", if it's a C++ compiler:
extern "C" void __stcall flycur2(char*, char*, int, int);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The original problem, with the linker error, indicates that the C/C++ code has specified "dllimport" but the library being linked against is not the export library from a corresponding build of the DLL. Note the __imp_ prefix to the name.
Now I notice something interesting. The name generated by building the DLL should be __imp_FLYCUR2 with one underscore before the FLYCUR2, but the linker error message has two underscores. This makes me think that the name as defined in the C/C++ code is actually _FLYCUR2.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You seem to have missed my post above. Please read it. (Yes, you do need void as well, but that's a secondary issue.)
edit: ...Oh, and extern "C", if it's a C++ compiler:
extern "C" void __stcall flycur2(char*, char*, int, int);
Yes I've read your post and I've tested
extern void __stdcall flycur2(char *,char *,int,int);
flycur2(filename1,filename2,n1,n2);
and I've got the following error
Error1error LNK2019: unresolved external symbol _flycur2@16 referenced in function _print_pages@0GRAFDLL.objGraf_09
I've also tested
extern "C" void __stdcall flycur2(char *,char *,int,int);
flycur2(filename1,filename2,n1,n2);
and I've got a syntax error.
I've tested so many different options now that I'm beginning to suspect if the linker really seesthe library? The .lib file is included in "Additional Dependencies" and the .dll file is in the working directory. That should be enough - or maybe not??
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
dumpbin -exports yourlibrary.lib
where yourlibrary.lib is the name of the export library. What does it show? Note that the names displayed will lack the __imp prefix.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
dumpbin -exports yourlibrary.lib
where yourlibrary.lib is the name of the export library. What does it show? Note that the names displayed will lack the __imp prefix.
Here is the result:
Dump of file sacudll.lib
File Type: LIBRARY
Exports
ordinal name
FLYCUR2
Summary
C9 .debug$S
14 .idata$2
14 .idata$3
4 .idata$4
4 .idata$5
E .idata$6
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
J__IMPORT_DESCRIPTOR_SacuPC_09 __NULL_IMPORT_DESCRIPTOR
SacuPC_09_NULL_THUNK_DATA FLYCUR2 __imp_FLYCUR2
FLYCUR2 __IMPORT_DESCRIPTOR_SacuPC_09 __NULL_IMPORT_DESCRIPTOR __imp_FLYCUR2
SacuPC_09_NULL_THUNK_DATA SacuPC_09.dll
FLYCUR2 SacuPC_09.dll
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
dumpbin -symbols thisobj.obj > dump.txt
and then open dump.txt in notepad and find all occurences of FLYCUR
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
dumpbin -symbols thisobj.obj > dump.txt
and then open dump.txt in notepad and find all occurences of FLYCUR
0DA 00000000 UNDEF notype () External | _flycur2@16
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The Fortran name has only one underscore, and the C code is looking for two.
The Win32 calling convention is that a leading underscore is added to the external name - in this case before the __imp_ is prepended - therefore giving the external name __imp__FLYCUR2 being asked for by the C code.
When you use the ALIAS: "FLYCUR2" the compiler assumes you know EXACTLY what name you want, and so does not put on the leading underscore.
Try adding DECORATE to your DEC$ ATTRIBUTES line. That keyword tells the compiler to treat the "alias" name as a base, and to add any appropriate "decorations" required by the calling convention.
- Lorri
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, finally!!!! Removing
!DEC$ ATTRIBUTES ALIAS: 'FLYCUR2' :: FLYCUR2
solved the problem. What a work for such a simple change! But I still wonder why it works when I call it from C#?
Thank you guys for your help!!!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page