Silverfrost Forums

Welcome to our forums

DLL basic!

13 May 2013 12:51 #12208

Anybody help with a quick note on how to create a DLL, how to make it like a plugin available only when the DLL is installed/added.

In other word. I have a fortran .exe and want to for some installation to provide extra options (via a dll) but also want to make sure that the .exe runs with (and without the DLL).

NEVER done this so I just need some basic help/explanation of workflow (an example would be great)

Sten

14 May 2013 7:30 #12210

Presumably you are writing in Fortran using FTN95.

Are you working from

  1. Plato or
  2. Visual Studio or
  3. A command line?

Are you using

  1. Win32 or
  2. .NET?
14 May 2013 9:38 #12213

Quoted from stenlou how to make it like a plugin available only when the DLL is installed/added.

At first using LoadLibrary() and GetProcAddress() winapi calls comes to mind. Problem is that Fortran 95 don't have procedure pointers. Maybe there is some trick to overcome that limitation? My Fortran skills are little bit limited but maybe someone more skilled could provide the answer?

Fortran 2003 makes this kind of things easy. Below is a Fortran 2003 sample to call procedure named hello that takes no parameters from test.dll.

module load_dll
  use, intrinsic :: iso_c_binding, only: c_f_procpointer, c_funptr, c_intptr_t, &
                      c_null_char, c_char, c_associated

  implicit none
  
  interface
     function LoadLibrary(lpFileName) bind(C, name='LoadLibraryA')
        use, intrinsic :: iso_c_binding, only: c_intptr_t, c_char
        character(kind=c_char) :: lpFileName(*) 
        !GCC$ ATTRIBUTES STDCALL :: LoadLibrary 
        integer(c_intptr_t) :: LoadLibrary 
     end function LoadLibrary 


     function GetProcAddress(hModule, lpProcName) bind(C, name='GetProcAddress')
       use, intrinsic :: iso_c_binding, only: c_funptr, c_intptr_t, c_char
       !GCC$ ATTRIBUTES STDCALL :: GetProcAddress
       type(c_funptr) :: GetProcAddress
       integer(c_intptr_t), value :: hModule
       character(kind=c_char) :: lpProcName(*)
     end function GetProcAddress      
  end interface

end module load_dll


module my_dll
  use, intrinsic :: iso_c_binding, only: c_f_procpointer, c_funptr, c_intptr_t, &
                      c_null_char, c_char, c_associated
  implicit none

  abstract interface
    subroutine hello() bind(C)
    end subroutine hello
  end interface
  
  integer(c_intptr_t) :: module_handle
  type(c_funptr) :: proc_address
  procedure(hello), bind(C), pointer :: my_proc
  
end module my_dll


program main
  use load_dll
  use my_dll
  implicit none
  
  
  module_handle = LoadLibrary(c_char_'test.dll'//c_null_char)
  if (module_handle == 0) stop 'Can''t load the DLL'

  proc_address = GetProcAddress(module_handle, c_char_'hello'//c_null_char)
  if (.not. c_associated(proc_address)) stop 'Can''t obtain the procedure address'

  call c_f_procpointer(proc_address, my_proc)
  call my_proc

end program main
Please login to reply.