- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
my problem is, that i got an existing .dll-File from an old, not Visual Fortran using Project (built with salford), and want to use the functions from this .dll in my new Visual Fortran Project.
I have no idea how to get this file correctly integrated.
Are there any commands in the source code i have to add?
Im using Visual Studio 2008 / Intel Visual Fortran Compiler Professional Edition 11.1 (on Windows XP).
So which steps i have to do?
Manuel
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you have import library file *.lib you can specify it to the linker and use functions from dll as it is your compiled code (be carefull on calling conventions of your dll).
If You do not hae *.lib file you can use dumpbin.exe to create it (google it).
Or you can use routines if you know their names by following code (i get only important parts how to call routine declared as
subroutine ROUTINE(I,Array,length)
integer*4 i,length
real*8 arrray(length)
...
! here is code how to call it
subroutine calldll(Arg1,Arg2,Arg3)
use kernel32
integer*4 Arg1,Arg3
real*8 Arg2(Arg3)
integer(HANDLE) iLib,iProc
interface
recursive subroutine RunDllSub(isub,i1,i2,i3,i4,i5,i6,i7,i8)
OPTIONAL :: i1,i2,i3,i4,i5,i6,i7,i8
end subroutine
end interface
pointer(pi1,Arg1)
pointer(pi2,Arg2)
pointer(pi3,Arg3)
iLib=LoadLibrary("library.dll"C)
iProc=GetProcAddress(iLib,"_ROUTINE@12"C) ! here You must know routine name how it was exported
pi1=LOC(Arg1)
pi2=LOC(Arg2)
pi3=LOC(Arg3)
call RunDllSub(%VAL(iProc),%VAL(pi1),%VAL(pi2),%VAL(pi3))
return
end subroutine
recursive subroutine RunDllSub(sub,i1,i2,i3,i4,i5,i6,i7,i8)
OPTIONAL :: i1,i2,i3,i4,i5,i6,i7,i8
external sub
if (present(i8)) then
call sub(i1,i2,i3,i4,i5,i6,i7,i8)
elseif (present(i7)) then
call sub(i1,i2,i3,i4,i5,i6,i7)
elseif (present(i6)) then
call sub(i1,i2,i3,i4,i5,i6)
elseif (present(i5)) then
call sub(i1,i2,i3,i4,i5)
elseif (present(i4)) then
call sub(i1,i2,i3,i4)
elseif (present(i3)) then
call sub(i1,i2,i3)
elseif (present(i2)) then
call sub(i1,i2)
elseif (present(i1)) then
call sub(i1)
else
call sub()
endif
end subroutine
Jakub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi and thanks for the answer,
but if i try to compile it i get the following error messages:
Error 1 error #6406: Conflicting attributes or multiple declaration of name. [ARG2] C:\Dokumente und Einstellungen\hoppm\Eigene Dateien\Visual Studio 2008\Projects\Wasdamta_test\Wasdamta_test\calldll.F90 16
Error 2 error #6406: Conflicting attributes or multiple declaration of name. [ARG3] C:\Dokumente und Einstellungen\hoppm\Eigene Dateien\Visual Studio 2008\Projects\Wasdamta_test\Wasdamta_test\calldll.F90 17
Error 3 error #7098: A dummy argument object cannot be a pointee. [ARG1] C:\Dokumente und Einstellungen\hoppm\Eigene Dateien\Visual Studio 2008\Projects\Wasdamta_test\Wasdamta_test\calldll.F90 4
Error 4 Compilation Aborted (code 1) C:\Dokumente und Einstellungen\hoppm\Eigene Dateien\Visual Studio 2008\Projects\Wasdamta_test\Wasdamta_test\calldll.F90 1
I changed this two lines as follows:
iLib=LoadLibrary("C:/tmp/SE_Wasdamta.dll"C)
iProc=GetProcAddress(iLib,"_FTN_HKRIT@0"C)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am sorry.
I am adding example of how to do it.
After you build solution please copy compiled dll testdll.dll to directory with exe file (to be found by exe file).
I hope it will work (I put routine calling dll to module because compiler has not problem with interface there.
(in GetProcAddres I used only "ROUTINE"C because intel fortran does not use @..., it depends on compiler)
Jakub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you very much, this example helped me a lot.
But how can i get some resulting values from functions of the .dll?
How can i write/use the results?
Manuel
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ivalue=iRunDllFunc(....)
parameters are the same as call RundllSub
IRunDllunc is defined in example
Jakub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, but the resulting values seem to be huge integer Values but i want (and expected) to get double precision Values.
Is there a clue to get the resulting values transformed or have i to change the source code of the function (iRunDllFunc) in order to get double precision values?!
This is the source code of my function call:
[fortran] double precision function tp(p) use kernel32 integer(HANDLE) iLib,iProc double precision p double precision point1 pointer(pp,point1) iLib=LoadLibrary("SE_Wasdamta.dll"C) iProc=GetProcAddress(iLib,"FTN_TP"C) ! here You must know routine name how it was exported pp=LOC(p) tp=iRunDllFunc(%VAL(iProc),%VAL(pp)) return end function[/fortran]
And for tp i always get the value of: 538976288.000000; even for different input values of p.
Is that the position of the value inside the memory? If, how can i get the value of it?
Any suggestion? What did i wrong?
Thanks a lot for your effort.
Manuel
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
in this case define in rundllsub.f90 function for example
[fortran]recursive real*8 function rRunDllFunc(isub,i1,i2,i3,i4,i5,i6,i7,i8) OPTIONAL :: i1,i2,i3,i4,i5,i6,i7,i8 external isub if (present(i8)) then rRunDllFunc=isub(i1,i2,i3,i4,i5,i6,i7,i8) elseif (present(i7)) then rRunDllFunc=isub(i1,i2,i3,i4,i5,i6,i7) elseif (present(i6)) then rRunDllFunc=isub(i1,i2,i3,i4,i5,i6) elseif (present(i5)) then rRunDllFunc=isub(i1,i2,i3,i4,i5) elseif (present(i4)) then rRunDllFunc=isub(i1,i2,i3,i4) elseif (present(i3)) then rRunDllFunc=isub(i1,i2,i3) elseif (present(i2)) then rRunDllFunc=isub(i1,i2) elseif (present(i1)) then rRunDllFunc=isub(i1) else rRunDllFunc=isub() endif end function [/fortran]add interface to this new routine and use this. You can define routines for different returning types.
Jakub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I added a new function as described above and wrote an Interface as follows:
[fortran]recursive real*8 function rRunDllFunc(isub,i1,i2,i3,i4,i5,i6,i7,i8) use ifwinty integer(HANDLE) isub,i1,i2,i3,i4,i5,i6,i7,i8 OPTIONAL :: i1,i2,i3,i4,i5,i6,i7,i8 end function[/fortran]
But I still get the same value.
Also tried it with a double precision function:
[fortran]recursive double precision function dRunDllFunc(isub,i1,i2,i3,i4,i5,i6,i7,i8) ...[/fortran]but again no change of the value!?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I do not know which compiler creates Dll but may be that there is difference how routine returns its value back. I think standard is that value is passed in ST0 registry but IVF assumes different passing procedure.
Are you able to debug dll and look at its return code (in assembler Ctrl+Alt+D)?
If not, display registers Ctrl+Alt+G (then right mouse button on it and select Floating point)and set breakpoint at the end of rRunDllFunc. Look at registers, in ST0 should be return value of your routine (see attachement). If not there is probably problem in routine in your dll.
Jakub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The ST0 value is exactly the value i expected, so i think there is no problem inside the routine, but how can i get this value now?
[bash]EAX = 20202020 EBX = 0012FF6C ECX = 0020001E EDX = 7FFFFFFF ESI = 00000000 EDI = 067AF9D4 EIP = 004015A8 ESP = 0012FD60 EBP = 0012FDA8 EFL = 00000206 ST0 = +1.5183624387684500e+0002 ST1 = +3.7334949153037572e+0007 ST2 = +4.7443639793396927e+0008 ST3 = +0.0000000000000000e+0000 ST4 = +0.0000000000000000e+0000 ST5 = +0.0000000000000000e+0000 ST6 = -0.2241176083388291e+4426 ST7 = +5.3758132584073803e+0002 CTRL = 0360 STAT = 2020 TAGS = FCFF EIP = 10001E11 EDO = 0012FD38 0012FD9C = 41C0101010000000 [/bash]It has the same value even within the real and integer version of the function.
Thanks again for your quick answer.
Manuel
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[fortran]double precision function tp(p) use kernel32 integer(HANDLE) iLib,iProc double precision p double precision point1 pointer(pp,point1) real*8 rRunDllFunc ! important !!!! iLib=LoadLibrary("SE_Wasdamta.dll"C) iProc=GetProcAddress(iLib,"FTN_TP"C) ! here You must know routine name how it was exported pp=LOC(p) tp=rRunDllFunc(%VAL(iProc),%VAL(pp)) return end function [/fortran]
please use code like this (see line important !!!), i think that you does not use interface block and routine rRunDllRunc is assumed (by default) to have return value of real*4 kind.
Jakub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Adding this line mentioned above results in an Error:
Error 1 error #6637: This actual argument must be the name of an external user function or the name of an intrinsic function. [%%VAL] C:\Dokumente und Einstellungen\hoppm\Eigene Dateien\Visual Studio 2008\Projects\calldll2\Console1\Console1\Source1.F90 42I also tried (without adding the line above) to change the declaration of all other used "double precision" variables and functions in the source code to: "real*8" but it still returns the wrong value (same as before).
[fortran] real*8 function tp(p) use kernel32 integer(HANDLE) iLib,iProc real*8 p real*8 point1 pointer(pp,point1) !real*8 rRunDllFunc iLib=LoadLibrary("SE_Wasdamta.dll"C) iProc=GetProcAddress(iLib,"FTN_TP"C) ! here You must know routine name how it was exported pp=LOC(p) tp=rRunDllFunc(%VAL(iProc),%VAL(pp)) print*,tp return end function[/fortran]
and:
[fortran]recursive real*8 function rRunDllFunc(isub,i1,i2,i3,i4,i5,i6,i7,i8) OPTIONAL :: i1,i2,i3,i4,i5,i6,i7,i8 external isub if (present(i8)) then rRunDllFunc=isub(i1,i2,i3,i4,i5,i6,i7,i8) elseif (present(i7)) then rRunDllFunc=isub(i1,i2,i3,i4,i5,i6,i7) elseif (present(i6)) then rRunDllFunc=isub(i1,i2,i3,i4,i5,i6) elseif (present(i5)) then rRunDllFunc=isub(i1,i2,i3,i4,i5) elseif (present(i4)) then rRunDllFunc=isub(i1,i2,i3,i4) elseif (present(i3)) then rRunDllFunc=isub(i1,i2,i3) elseif (present(i2)) then rRunDllFunc=isub(i1,i2) elseif (present(i1)) then rRunDllFunc=isub(i1) else rRunDllFunc=isub() endif end function[/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I missed that function tp is declared in module and there is interface to rRunDllfunc above it before contains. It was bad guess.
I do not precisely know what is happening. Can you put your code (and dll) to forum to test it? At least source file which calls rRunDllFunc?
Jakub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I missed that function tp is declared in module and there is interface to rRunDllfunc above it before contains. It was bad guess.
But I still think the problem is in type mismatch.
I do not precisely know what is happening. Can you put your code (and dll) to forum to test it? At least source file which calls rRunDllFunc?
Jakub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you are getting the same value back when you apparently send a different value to the DLL function, perhaps you are actually sending the same value each time?
I note you are always sending the location of a value. Since this location will not change whatever value you send, unless it is a different location, perhaps this explains it. Maybe you should send the VALUE itself. Then perhaps you will get a different value back when you change the VALUE sent?
Test bysupplying the function withtwo different values stored in different locations?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I must apologize, it is my problem. Routine rRunDllFunc should start like ...
[bash] recursive real*8 function rRunDllFunc(isub,i1,i2,i3,i4,i5,i6,i7,i8)
OPTIONAL :: i1,i2,i3,i4,i5,i6,i7,i8
external isub
real*8 isub
[/bash]
isub was assumed to be integer*4 (by default) not real*8 and it produces problem with value conversion
Jakub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks! Now it runs!
You dont have to apologize, you did a great job and helped me alot!
Manuel

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