- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, I am writing a Fortran 2003 program which will make calls to a C++ dynamic link library. An initial call to the .dll seems to work fine however, consecutive calls return unexpected results.
My dll is composed of the files util_lib.cpp a header file util_lib.h
Heres the util_lib.cpp, the routine readLongInt should simply print a long int:
[cpp]#include#include "util_library.h" extern "C" { UTIL_API void CALLING readLongInt(long a) { std::cout<<"Here is a long int: "<<<"\n"<<:ENDL>
Here is the associated header file util_lib.h:[cpp]#pragma once #ifdef UTIL_EXPORTS #define UTIL_API __declspec(dllexport) #else #define UTIL_API __declspec(dllimport) #endif #define CALLING __stdcall extern "C" { UTIL_API void CALLING readLongInt(long); } [/cpp]
Here is the Fortran program which calls readLongInt 3 times in succession:[...
1 Solution
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is the smoking gun:
!DEC$ATTRIBUTESALIAS:'_readLongInt@4'::read_long
Any time you explicitly put @n in an alias, in an attempt to solve linking issues, you're just creating trouble. The reason is that the @n suffix denotes a STDCALL convention routine, and if you don't tell Fortran you're calling a STDCALL routine, you get stack corruption as the stack gets popped twice on every call.
In the C++ code, you have the define for CALLING specifying STDCALL.
The solution is to replace that directive with this:
!DEC$ATTRIBUTES STDCALL, DECORATE, ALIAS:'readLongInt'::read_long
You can remove the ATTRIBUTES VALUE directive, since STDCALL implies that, or leave it in.
An alternative is to remove the __stdcall from the #define and use this interface instead:
!DEC$ATTRIBUTESALIAS:'_readLongInt@4'::read_long
Any time you explicitly put @n in an alias, in an attempt to solve linking issues, you're just creating trouble. The reason is that the @n suffix denotes a STDCALL convention routine, and if you don't tell Fortran you're calling a STDCALL routine, you get stack corruption as the stack gets popped twice on every call.
In the C++ code, you have the define for CALLING specifying STDCALL.
The solution is to replace that directive with this:
!DEC$ATTRIBUTES STDCALL, DECORATE, ALIAS:'readLongInt'::read_long
You can remove the ATTRIBUTES VALUE directive, since STDCALL implies that, or leave it in.
An alternative is to remove the __stdcall from the #define and use this interface instead:
[fortran] subroutine read_long(a) bind(C,NAME="readLongInt") use iso_c_binding integer(c_int),value :: a end subroutine read_long [/fortran]
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is the smoking gun:
!DEC$ATTRIBUTESALIAS:'_readLongInt@4'::read_long
Any time you explicitly put @n in an alias, in an attempt to solve linking issues, you're just creating trouble. The reason is that the @n suffix denotes a STDCALL convention routine, and if you don't tell Fortran you're calling a STDCALL routine, you get stack corruption as the stack gets popped twice on every call.
In the C++ code, you have the define for CALLING specifying STDCALL.
The solution is to replace that directive with this:
!DEC$ATTRIBUTES STDCALL, DECORATE, ALIAS:'readLongInt'::read_long
You can remove the ATTRIBUTES VALUE directive, since STDCALL implies that, or leave it in.
An alternative is to remove the __stdcall from the #define and use this interface instead:
!DEC$ATTRIBUTESALIAS:'_readLongInt@4'::read_long
Any time you explicitly put @n in an alias, in an attempt to solve linking issues, you're just creating trouble. The reason is that the @n suffix denotes a STDCALL convention routine, and if you don't tell Fortran you're calling a STDCALL routine, you get stack corruption as the stack gets popped twice on every call.
In the C++ code, you have the define for CALLING specifying STDCALL.
The solution is to replace that directive with this:
!DEC$ATTRIBUTES STDCALL, DECORATE, ALIAS:'readLongInt'::read_long
You can remove the ATTRIBUTES VALUE directive, since STDCALL implies that, or leave it in.
An alternative is to remove the __stdcall from the #define and use this interface instead:
[fortran] subroutine read_long(a) bind(C,NAME="readLongInt") use iso_c_binding integer(c_int),value :: a end subroutine read_long [/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
While you are fixing up that interface change C_INT to C_LONG to avoid future confusion/problems.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Problem solved, thanks!
so the lesson is, decoration in the alias is incompatablewith C or STDCALL attribute.
@IanH
thanks for spotting that, I will change it right away. One of my other cpp dlls uses an unsigned int argument, I was going to pass itinteger*4, but perhaps I should rethink?
so the lesson is, decoration in the alias is incompatablewith C or STDCALL attribute.
@IanH
thanks for spotting that, I will change it right away. One of my other cpp dlls uses an unsigned int argument, I was going to pass itinteger*4, but perhaps I should rethink?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The @n decoration is specific to STDCALL. If you had specified STDCALL in the Fortran, it would have worked. I suggested using the DECORATE attribute to let the compiler worry about the decoration, but I think the better solution is to remove the STDCALL on the C++ side.

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