forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How to load a Fortran function from C++ (instructions)

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> 64-bit
View previous topic :: View next topic  
Author Message
StamK



Joined: 12 Oct 2016
Posts: 159

PostPosted: Tue Jun 20, 2017 11:28 am    Post subject: How to load a Fortran function from C++ (instructions) Reply with quote

In the 32bit world it was possible for the linker to create a dll AND a lib file (via the archive command).
This was particular useful as it allowed a Qt or VC++ program to call a Fortran function directly using

Code:

extern "C" void FortranFunction(...)


Now however it is necessary to use LoadLibraryA if using VC++, as follows:



Code:

#include "stdafx.h"
#include "windows.h"
//extern "C" void VERYSIMPLE(int* input);    //old way, with .lib file present



extern "C" {
   typedef void(*VERYSIMPLE_ptr)(int* input);
}

void VERYSIMPLE(int* input)
{
   auto hdl = LoadLibraryA("fortran.dll");
   if (hdl)
   {
      auto the_func = reinterpret_cast< VERYSIMPLE_ptr >(GetProcAddress(hdl, "VERYSIMPLE"));
      if (the_func)
         the_func(input);   
      else
         printf("no function\n");

      FreeLibrary(hdl);
   }
   else
      printf("no library\n");

}



int _tmain(int argc, _TCHAR* argv[])
{

   int input1 = 12;
        VERYSIMPLE(&input1);
   system("pause");
   return 0;
}


Last edited by StamK on Tue Jun 20, 2017 11:37 am; edited 1 time in total
Back to top
View user's profile Send private message
StamK



Joined: 12 Oct 2016
Posts: 159

PostPosted: Tue Jun 20, 2017 11:31 am    Post subject: Reply with quote

If using Qt with MSVC, then it is possible to use LoadLibraryA as above, or use Qt's QLibrary.

Code:

#include <QLibrary>

void QW_GET_VALC(int* IWIN, int* IFLD, char* CH)
{
    typedef void (*MyPrototype)(int* IWIN, int* IFLD, char* C);
    MyPrototype myFunction = (MyPrototype) QLibrary::resolve("llib1", "QW_GET_VALC");
    if (!myFunction)
    {
        qWarning()<<"\nError with function QW_GET_VALC";
    }

    if (myFunction)
        myFunction( IWIN,  IFLD,  CH);
}
Back to top
View user's profile Send private message
StamK



Joined: 12 Oct 2016
Posts: 159

PostPosted: Tue Jun 20, 2017 11:35 am    Post subject: Reply with quote

If passing a string from C++ to Fortran, be aware that you need to add in C++ the string size (strlen) as an extra int parameter at the end (as per Silverfrost's documentation).

In VC++ this works fine, but NOT in Qt. Not sure where the bug is (if it is Qt or Silverfrost), but a temporary solution is to create a VC++ DLL that calls the Fortran DLL, and Qt will call the VC++ DLL.
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7912
Location: Salford, UK

PostPosted: Tue Jun 20, 2017 12:48 pm    Post subject: Reply with quote

StamK

It isn't necessary to use LoadLibrary when calling a C++ function from 64 bit FTN95.

The standard approach is to use extern "C" and export the functions from the DLL. Then load the DLL via SLINK64.

In the Fortran code you should declare the DLL functions using C_EXTERNAL and, when passing strings, use STRING, INSTRING or OUTSTRING.
Back to top
View user's profile Send private message AIM Address
StamK



Joined: 12 Oct 2016
Posts: 159

PostPosted: Tue Jun 20, 2017 1:13 pm    Post subject: Reply with quote

Hi Paul, thanks for the useful input - but this is for Fortran calling a C++ DLL, while I have described a C++ executable loading a Fortran DLL.
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7912
Location: Salford, UK

PostPosted: Tue Jun 20, 2017 3:34 pm    Post subject: Reply with quote

OK. I missed that.

Microsoft have a lib.exe app that creates mylib.lib from mylib.dll and mylib.def.
Back to top
View user's profile Send private message AIM Address
StamK



Joined: 12 Oct 2016
Posts: 159

PostPosted: Wed Jun 21, 2017 4:59 pm    Post subject: Reply with quote

I had tried that lib.exe command and it didn't work at first, but I found out that Qt was failing for another reason.

I can confirm that Qt can access the DLL with the LIB file created that way.

The script below removes the extra lines, cleans the rows and adds EXPORTS at the beginning of the DEF file, which is then used to create the LIB file. Assuming that the script is called libcreate.bat and the DLL file is called LIBRARIES.DLL, then it can be called as

Code:
libcreate.bat LIBRARIES


Code:
Code:

@echo off
if "%1"=="" goto blank
call del %1.def
for /f "usebackq tokens=4,* delims=_ " %%i in (`dumpbin /exports "%1.dll"`) do  echo %%i_%%j >> %1.def
call more +9 "%1.def" > "%1.def.new"
move /y "%1.def.new" "%1.def" >nul
copy %1.def temp.def
echo.EXPORTS>%1.def
type temp.def>>%1.def
del temp.def
lib /def:"%1.def" /out:"%1.lib"  /MACHINE:X64
goto DONE
:BLANK
echo No DLL file name present
:DONE
Back to top
View user's profile Send private message
StamK



Joined: 12 Oct 2016
Posts: 159

PostPosted: Fri Jun 30, 2017 3:43 pm    Post subject: Reply with quote

If the Fortran subroutine/function is inside a module, then it will be necessary to use the LoadLibraryA method as Silverfrost exports it as MODULENAME!FORTRAN_SUBROUTINE and cannot be found via extern "C" (or at least I am not able to put a name with an exclamation mark). Unless there is a way to tell Silverfrost to export in a different name?

Thanks
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7912
Location: Salford, UK

PostPosted: Fri Jun 30, 2017 9:14 pm    Post subject: Reply with quote

SLINK64 has an "alias" option that is described in the help file at FTN95->x64 platform->Using the 64 bit linker. It might be useful in this context. The "map" option may also be useful in that it may show the internal representation of the module function.
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> 64-bit All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group