- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
We used to work with static library and now decided to switch to dll. Here is the problem that we are facing. I have a large source file that contains hundreds of subroutines, but they can be classified into two kind of subroutines, one kind is the system subroutines (syssrc.for) which can not be reached by the users, while the other kind is the user subroutines (usr.for which are called by some routines in syssrc.for) which users can modify or print out some data from them.
The procedure I did is that,
1. Add !DEC$ ATTRIBUTES DLLEXPORT :: "nameofsubroutines" under every subroutines in usr.for.
2. Build dll using usr.for to generate dllusr.dll and dllusr.lib files.
3. Add !DEC$ ATTRIBUTES DLLEXPORT :: "nameofsubroutines" under every subroutines in syssrc.for
4. Build dll using syssrc.for and dllusr.lib (need dllusr.dll in the same folder), to generate dllsyssrc.dll and dllsyssrc.lib.
5. Create a application with main program and link dllsyssrc.lib.
In this way, I could call the subroutines in both usr.for and syssrc.for. But the usr.for that should be modified by users can not be overwritten or replaced the one in usr.for since these subroutine are embedded in dllsyssrc.lib.
Does anyone has idea what kind of modifications or configurations should I set to let the project ignore the usr.for in dllsyssrc.lib and use the updated one?
Thank you
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That'a not the issue here. It has to do with which routine does the linker find first, and can you get the linker to avoid complaining about duplicates. I think it's possible but I have to work out an example.
A key is that the reference to the routine you want to substitute MUST be in the main program - it can't be referenced from the DLL.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here are sample codes that I created to illustrate the function.
usr.for
SUBROUTINE USRDIVD(A,B,C) !DEC$ ATTRIBUTES DLLEXPORT :: USRDIVD IMPLICIT REAL*8(A-H,O-Z) WRITE(*,*) "PAUSE" PAUSE RETURN END
syssrc.for
SUBROUTINE ADD(A,B,C) IMPLICIT REAL*8(A-H,O-Z) !DEC$ ATTRIBUTES DLLEXPORT :: ADD C = A+B WRITE(*,*) "C = A+B=",C CALL MINUS(A,B,C) CALL USRDIVD(A,B,C) RETURN END C SUBROUTINE MINUS(A,B,C) !DEC$ ATTRIBUTES DLLEXPORT :: MINUS IMPLICIT REAL*8(A-H,O-Z) C = A-B WRITE(*,*) "C = A-B",C RETURN END C
Main program
PROGRAM MAIN !DEC$ ATTRIBUTES DLLIMPORT :: ADD IMPLICIT REAL*8 (A-H,O-Z) A = 10.D0 B = 15.D0 CALL ADD(A,B,C) END PROGRAM MAIN SUBROUTINE USRDIVD(A,B,C) !DEC$ ATTRIBUTES DLLIMPORT :: USRDIVD WRITE(*,*) "PAUSEHAHAH" PAUSE RETURN END
How can I use user defined USRDIVD instead of the default one?
Thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Liang
You will need to create the Interface Module. It should something like this:
Module myModule
Interface
Subroutine mySub(myArg1, myArg2,..)
Integer::myArg1,...
Real*8::myARg2,...
End Subroutine
End Interface
End Module
Then you must compile the module and include the following statements in your calling program
include myLib.LIB
Use myModule
Michael
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, Michael
I have created a module (mod.for) as you suggested
MODULE DIVDMOD INTERFACE SUBROUTINE USRDIVD(A,B,C) IMPLICIT REAL*8 (A-H,O-Z) END SUBROUTINE USRDIVD END INTERFACE END MODULE DIVDMOD
and also modified the syssrc.for to be
SUBROUTINE ADD(A,B,C) USE DIVDMOD IMPLICIT REAL*8(A-H,O-Z) !DEC$ ATTRIBUTES DLLEXPORT :: ADD C = A+B WRITE(*,*) "C = A+B=",C CALL MINUS(A,B,C) CALL USRDIVD(A,B,C) RETURN END C SUBROUTINE MINUS(A,B,C) !DEC$ ATTRIBUTES DLLEXPORT :: MINUS IMPLICIT REAL*8(A-H,O-Z) C = A-B WRITE(*,*) "C = A-B",C RETURN END
Then I compile these two files together with dllusr.lib to generate a new dllsyssrc.lib.
It seems that it still doesn't work in this case. The multiple definitions that follows the main program is sill not able to replace the one in dll.
Thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Liang
You also need to add the alias attribute:
!DEC$ATTRIBUTES DLLEXPORT :: xxx
!DEC$ATTRIBUTES ALIAS: 'xxx' :: xxx
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In the compiler's examples directory you will find a "DLL_Shared_Data" example. The main point is that you have to get the linker to make the module variable appear in a shared data segment. Otherwise, the DLL and the EXE will have separate copies of the module data, causing updates in one to be unseen in the other.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That'a not the issue here. It has to do with which routine does the linker find first, and can you get the linker to avoid complaining about duplicates. I think it's possible but I have to work out an example.
A key is that the reference to the routine you want to substitute MUST be in the main program - it can't be referenced from the DLL.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello, I finally came up a solution.
The user could actually create there own dllusr.dll by modifying the usr.for and then replace the one that exist in the final application folder.
For example, the user could save
09 |
SUBROUTINE USRDIVD(A,B,C) |
10 |
!DEC$ ATTRIBUTES DLLEXPORT :: USRDIVD |
11 |
WRITE (*,*) "PAUSEHAHAH" |
12 |
PAUSE |
13 |
RETURN |
14 |
|
in a separate file and generate a new dll file and replace the old one before compiling the application.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page