Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
89 Views

interface between Delphi Pascal and Fortran

I have an existing application that uses Delphi Pascal to create a windows GUI that gathers data and calls fortran routines from a fortran DLL. The sequence is complicated by the fact that there is an additional dll written in pascal that is used as the interface between the fortran and the pascal program.

The pascal program has function calls that get and put data to an SQL database. The fortran dll gets access to those functions through the routines defined in the pascal dll.

When the call is made to pass the collected data to the fortran dll to do the engineering calculations, the pascal dll is first loaded and initialized with some related data. Then the fortran dll function is called and the first thing it does is get the pointers to the functions in the pascal dll it needs to do its job (it will get and put data to the SQL database.)

 

What I want to do is make the pascal dll routines a part of the main program rather than a dll.

 

How do I change the interface definition in the fortran code to do this?

0 Kudos
4 Replies
Highlighted
Beginner
89 Views

Here is more info

The fortran dll has the following definition of a function it expects from an external dll it will read.

interface
        integer*4 function GetPointer(i,irra)
            !dec$ attributes stdcall, dllimport :: GetPointer
            !dec$ attributes reference :: GetPointer, irra, i
            integer*4 irra,i
        end function
    end interface

and following that is the following line:

Pointer(pGetPointer, GetPointer)

 

The fortran dll has the following exported function defined:

 SUBROUTINE CORETG(nfunci, erri, pblui)
      !DEC$ ATTRIBUTES STDCALL, DLLEXPORT, REFERENCE, ALIAS:'_CORETG' :: CORETG

One of its first tasks is to load the pascal dll and get the address of a function in it:

pdllDelphi = LoadLibrary(dllaux) (where dllaux is a string containing the name of the dll)

pGetPointer = GetProcAddress(pdllDelphi, 'GetPointer'C)

And this function then calls GetPointer:

So when the main program runs, it loads the two dlls discussed above, calls an initialization function in the pascal dll that populates an array of string for later use. Then it calls the exported fortran dll function CoretG which then calls the pascal function GetPointer, which in turn calls functions that are defined in the main program.

I believe this structure developed historically, probably with the fortran code used many years ago, and the windows application wrapped around it. What I want to do is eliminated the pascall dll, and let the fortran dll call the main program functions directly.

 

0 Kudos
Highlighted
Black Belt
89 Views

I may not be quite following what you are trying to do, but how do you anticipate that the Fortran DLL would get the addresses of the procedures in the main program that it needs to call?

There are a couple of options, but one that is more typical is that the main program would pass to the DLL the relevant addresses as arguments of a call to a procedure in the DLL.  Is that what you envisage?

If memory serves me correctly, you can also use GetProcAddress to look up the addresses of explicitly exported procedures in executable modules as well, but this is rather atypical, and results in a tight binding between the DLL and executable that sort of defeats the point of having stuff in a DLL in the first place.  The existence of the pascal DLL may have been a work around for this.

0 Kudos
Highlighted
Black Belt
89 Views

There are a number of possibilities, and you need to decide which fits your needs best. The simplest solution, if feasible, is to pass procedure pointers (of your callback procedures, for instance) as arguments from the EXE to the DLL. The DLL can call those callback procedures in the EXE and can also call procedures from other DLLs. If you can do this, the DLL can be built before you have written any code for the EXE, and when you build the EXE later you can use the import library that was created when you built the DLL.

If you do not wish to pass procedure pointers as arguments, the build process gets a bit more complicated. There is a recursive dependence between the EXE and DLL, and manual intervention is needed to resolve that recursion.

For simplicity, let us set aside Delphi, STDCALL and the database, and consider a situation where you build a Fortran EXE that calls a subroutine from a Fortran DLL, and the DLL calls a routine in the EXE. Here is the source code for the DLL:

subroutine fdsub(i)
!dec$ attributes dllexport :: fdsub                      ! this procedure
!dec$ attributes dllimport :: fmsub                      ! in EXE
call fmsub(i,j)
write(*,*)'In fdsub, i,j = ',i,j
return
end subroutine

We attempt to build the DLL from this:

     ifort /LD fdsub.f90

The DLL build fails, but there is partial success, in that the DLL's import library fdsub.lib is produced.

We can now build the EXE and produce its exports library. The code for the EXE:

program tst
integer i
!dec$ attributes dllimport :: fdsub
i=17
call fdsub(i)                       ! DLL procedure
write(*,*)'Back in main'
end program

subroutine fmsub(i,j)               ! will get called from DLL
!dec$ attributes dllexport :: fmsub
j=i*i
write(*,*)'In fmsub, i,j = ',i,j
return
end subroutine

The command to build the EXE:

     ifort fexe.f90 fdsub.lib

The EXE now gets built, and its export library is generated. We now repeat the DLL build, but with this export library added, and this time the DLL build succeeds.

     ifort /LD fdsub.f90 fexe.lib

We now run the EXE, and see the output

      In fmsub, i,j =           17         289
      In fdsub, i,j =           17         289
      Back in main

You can build on this, replacing the static procedure names and references with calls to GetProcAddress, LoadLibrary, etc.

0 Kudos
Highlighted
Beginner
89 Views

Thanks, guys. I had limited experience with DLL's when I got handed this project. Yesterday when I packed up to go home, I still did not have any responses to my question but I was still thinking about it. Overnight I came to the conclusion that the solution was to pass in the pointers to the functions that I need to use in the fortran DLL. Which is exactly the solution you guys gave me. I had just finished outlining my solution to a fellow developer who has equally as little experience with DLL's as I when I read your responses. So thanks for the help. I now have a plan and will be able to make a lot of progress today. Plus I can become a DLL expert!

0 Kudos