Error access violation reading 0x0000000a when call fortran dll made by gfortran

1

1.FORTRAN source (main.for)

      integer function mysum(a, b)
        !DEC$ATTRIBUTES DLLEXPORT,STDCALL :: mysum
        !DEC$ATTRIBUTES VALUE :: a, b

        integer a,b

        mysum = a + b

        return

      end function mysum
  1. make dll
gfortran main.for -shared -o fordll.dll
  1. call dll
#include <stdio.h>
#include <iostream>
#include <windows.h>

using namespace std;
typedef int(_stdcall * MYSUM)(int a, int b);

int main()
{
    int a=10,b=20;
    HINSTANCE hLibrary = LoadLibrary("fordll.dll");
    if (hLibrary == NULL)
    {
        cout << "can't find the dll file" << endl;
        return -1;
    }
    MYSUM fact = (MYSUM)GetProcAddress(hLibrary, "mysum");
    if (fact == NULL)
    {
        cout << "can't find the function file." << endl;
        return -2;
    }

    try
    { 
        cout << fact(a,b);
    }
    catch(...)
    { }

    FreeLibrary(hLibrary); 
    return 0;
}
  1. ERROR
Exception Access Violation reading 0x0000000A

why? if the fortran source file is comppiled by Compad Visual fortran or Inter fortran, it works well. However, it doesn't work with gcc or gfortran. What's wrong?

gcc
dll
fortran
gfortran
asked on Stack Overflow Nov 14, 2020 by PyEngine • edited Nov 14, 2020 by Vladimir F

1 Answer

0

You are using special directives to alter the calling conventions

    !DEC$ATTRIBUTES DLLEXPORT,STDCALL :: mysum
    !DEC$ATTRIBUTES VALUE :: a, b

However, these are only valid for the DEC compiler sand its descendant Intel Fortran.

GCC use !GCC$ directives instead. Use them, they are pretty much the same as the DEC ones. See https://gcc.gnu.org/onlinedocs/gfortran/ATTRIBUTES-directive.html#ATTRIBUTES-directive Just change coppy and paste the DEC directives and change DEC to GCC.

Alternatively, change the code to pass-by-reference and ditch the VALUE attribute. The STDCALL attribute is relevant for 32-bit Windows only.


In modern Fortran it is much better to use

integer function mysum(a, b) bind(C,name="mysum")
        
        integer, value :: a, b

(ignoring the stdcall issue, which can be just deleted in the C++ code).

answered on Stack Overflow Nov 14, 2020 by Vladimir F • edited Nov 14, 2020 by Vladimir F

User contributions licensed under CC BY-SA 3.0