Enable to Call Fortran DLL many times using VB.net

Enable to Call Fortran DLL many times using VB.net

Hi

 I have created Dll using fortran and I could able to call some subroutines from this Dll file using VB.net and passing the arrays I would like to pass between Fortran Dll and VB.net.But I'm facing a problem to call the subroutine more that one time, in other wards when I run the VB.net(interface) and Run amodel (Which will call the subroutine from Dll file), the simulation will be done without any problems. But if I opened a new model and try to run again I could not call this subroutine again from the Dll (it seems the Dll is busy in some thing, although the simulation is done), so I have to close all the interface to be able to run that model. I hope I could be able to describe my problem, What iam asking for if there is any setting I have to take in consideration while i'm creating the Dll file to over come this problem.

this is the fortran subroutine I'm using

Subroutine FortranDLL(A,IA)
!MS$ATTRIBUTES DLLEXPORT, ALIAS: 'FORTRANDLL' :: FortranDLL 
IMPLICIT REAL*8 (A-H,O-Z)
DIMENSION A(5000001),IA(5000001)
OPEN(unit=1000,file=
+'C:\Sams2000\Applications\ATTIF2000\Engine\AttifSavedResults.txt')
CALL ATIFLO00(A,IA)
CLOSE (1000)
Return
End Subroutine FortranDLL

Many thanks

Ahmed

 

31 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

In the example you show, you are opening (and writing) the same file each time.  Is that really what you want?

What error or behavior do you get that suggests to you that the DLL is "busy"?

I will commnent that a frequent point of confusion in a situation such as this is that some Fortran variables may retain their state across calls to the routine. You need to make sure that all variables are run-time initialized on each entry to the Fortran code.

Steve - Intel Developer Support

Hi Steve

Thanks a lot for your reply and help. Yes I need to open this file every time I run a model to save some results on it, and I have doubt that might be the source of the problem so I have commented it but the problem still exist. I did not get any error message from the interface(VB.net), but by debauging this is the last position that the interface crash , the interface couldont able to call this subroutine fro the Dll file again. In the same time after I have finished run the model for the first time without problem and the simulation is done, the I cannot replace the Dll file from where it is stored in my computer which give me indication it is still using some where else although the simulation is done.please let me know if there is any thing not clear for you.

Many thanks

Ahmed 

Oh, I think I see.  You didn't add STDCALL, REFERENCE to the ATTRIBUTES directive. This results in stack corruption.

Please use:

!DIR$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE, ALIAS: 'FORTRANDLL' :: FortranDLL

Steve - Intel Developer Support

I have tried what you sent me but unfortunately I have this problem

Unable to find an entry point named 'FORTRANDLL' in DLL 'C:\Sams2000\Applications\ATTIF2000\Engine\ATTIFDLLENG.dll'

and I would like to make sure if  the decleration you sent me is compitibale with powerstation , as I'm using it right now to be able to over write some some routines in the library i'm using.

many thanks

Ahmed

If you use !MS$ATTRIBUTES instead of !DIR$ ATTRIBUTES, then it should be compatible. Do you get the error when using Intel Fortran?

Steve - Intel Developer Support

No I have got this error using  Fortran Power station

and when I did use the decleration as you just tol me as 

Subroutine FortranDLL(A,IA)
!MS$ATTRIBUTES DLLEXPORT, ALIAS: 'FORTRANDLL' :: FortranDLL
!MS$ATTRIBUTES STDCALL:: FortranDLL
!MS$ATTRIBUTES REFERENCE:: FortranDLL
IMPLICIT REAL*8 (A-H,O-Z)
DIMENSION A(5000001),IA(5000001)
OPEN(unit=1000,file=
+'C:\Sams2000\Applications\ATTIF2000\Engine\AttifSavedResults.txt')
CALL ATIFLO00(A,IA)
CLOSE (1000)
Return
End Subroutine FortranDLL

I could be able to create the Dll and call it only once as previously done. So I think this not the souce of the problem

Many thanks

Ahmed

For PowerStation, you don't need the STDCALL and REFERENCE directives, but they should not hurt.  Your PowerStation is at least 16 years old, though, so perhaps it has some problems I am not aware of. I suggest using Dependency Walker to see what names the DLL exports.

Steve - Intel Developer Support

 No problem , So you think if I'm using Intel fortran with this decleration the problem will be solved, and what is the soucre of the proble as you think and dependding on that you sent me a new decleration ?

I do appreciate your continous and respected help

Many thanks

Ahmed

The problem is that there are two calling conventions used on 32-bit Windows, C and STDCALL.  VB uses STDCALL and PowerStation defaults to STDCALL.  Intel Fortran defaults to C, and if you don't adjust for this, the stack will be corrupted on each call to the Fortran code. Adding the STDCALL and REFERENCE attributes will make Intel Fortran use STDCALL the same way PowerStation did, and those directives will just reinforce PowerStation's defaults.

Steve - Intel Developer Support

Ok , if this is the source of the problem in case of intel fortran it should appear  with the  first call(which works fine in my case), not in the second call as in this case, is what i'm thinking in is correct ?

Many thanks

Ahmed

No - it would not show up until at least the second call, as the stack corruption occurs when the Fortran routine returns. Depending on what happens in the program, you might not notice a problem until a third or even later call.

Steve - Intel Developer Support

Many thanks Steve

I will convert to use Intel Fortran right now and I will let you know the status for the program

Really, your hrlp is always important for us

Many thanks

Ahmed

Hi Steve

I have used Intel fortran to build the Dll file as you recomended  , but I got anther problem . After the first run has been done (call FortranDLL(A,IA)) without any problem, If I tried to run anther model which mean doing the same call again  (call FortranDLL(A,IA)), the problem cames up as shown in the attached file . It is seems to me that the input file for the engine(DLL), which it will read, becomes busy so in the next call it will not be able to read it/access it . Am I correct , and do you have any suggestion to overcome this problem?. I don't know if the dll subroutine hass been returned why the files it used to read is still busy or used by anther program.

Many thanks

Ahmed 

Attachments: 

AttachmentSize
Download error.doc144.5 KB

Did you close unit 1 at the end of the first call?  If not, then doing an OPEN on the same unit and file will not reset the position of the file. You could also add a REWIND(1) after the OPEN if that's what you want, but I recommend making sure the unit is closed before the return.

Steve - Intel Developer Support

Hi Steve

I have closed this unit and now it is working, but still I have a question. If I have stopped the simulation,which means the  FortranDLL(A,IA) has been returned and there should not be any conection between the interface and the DLL file, am I right?. but accually this not the case , if I tried for example to delete or replace the DLL file after the simulation has been stopped I got a message that this file is being used by anther person . In addition if I have statred the same simulation again after stopping it (the same input), the results are different, iam afraid that the diffinations of the arrays inside the engine still the same as the previous simulation and it is not intiallized.I hope I could able to make it clear

Could you please clarfiy that for me.

Many thanks

Ahmed 

The DLL is not "returned" - it is still loaded into the address space. The only way for it to be "returned" is for a FreeLibrary call to be made on the library handle - and you can't do that, since it was VB that loaded it and it doesn't give you the handle. So the DLL will remain in use until the VB program exits.

Steve - Intel Developer Support

Ok, but if during the Dll engine I have defined arrays and common blocks during my calculation .when the engine done the first run and i would like to run a second run does all the declerations for the arrays and common blocks for the new problem will be new decleared or it is still the old arrays for the previous run.

Many Thanks

Ahmed

Any static data (COMMON, module variables, etc.) will be unchanged from the last run. You have the responsibility of making sure all variables get reinitialized when you start a new "run". They would only get reset if the DLL was unloaded and reloaded.

Steve - Intel Developer Support

really I do appreciate your great help all the time. but I still have one more question is ther is any way to unload or reload the dll file without closing the program (Interface) so every thing will be intialized automatically or I have to do that though the code, why question is that our code is too big and there is a room to miss some thing to intialize.

I would like to thank you one more time for your contious help

Ahmed

I do not know of a way to do this when VB has loaded the DLL for you. You will need to write code to do the initializations.

Steve - Intel Developer Support

Ok, I will do that, let me thank you one more time for your great help

Many thanks

Ahmed 

You can use something like this (I am writing it from memory) and it is C code.

    char *DllName="Fortran.dll";
    HMODULE FortranLib=LoadLibrary(DllName);
    typedef LPVOID(__cdecl *T_FortranFunction)(double *Array,int *ia);
    T_FortranFunction FortranFunction=(T_FortranFunction) GetProcAddress(FortranLib,"FORTRANFUNCTION"); // function name is exported uppercase
    FortranFunction(Array,ia);  //call to function

    BOOL retval=FreeLibrary(FortranLib);  //remove library from memory

   

If You want to use this approach You cannot link against Fortran.lib because linker creates initialisation of library instead You.

Sure - if you can figure out how to do something like this from VB it will work, but that's quite complex in VB, if possible at all, and loses a lot of VB's friendliness in syntax.

Steve - Intel Developer Support

Hi Steve

I have thought in some ways in VS to be able to load and unload the DLL file, and I think The only way to do that is using AppDomain in VS so I should be able to load and unload this AppDomain , I have done that but I'm facing a security problem while calling the subroutines from the Dll file , could you please help me to know if there problem I can manage from the dll or VS , I have attached the error I got while calling the Dll subroutine

Many thanks

Attachments: 

AttachmentSize
Download doc1.doc192.5 KB

Ahmed, sorry, I have never seen that before and would not be able to diagnose based on a screenshot. My guess, though, is that you can't do this. I would encourage you to solve the problem another way. For example, you could have VB call a Fortran DLL that itself used LoadLibrary and GetProcAddress to load the "real" DLL and then call FreeLibrary before returning.

Steve - Intel Developer Support

Hi Steve

Thank you so much for your reply, and I will be do appreciated if you just sent me an example to clarify the other way you suggested , I'm facing a lot of problems with the way I'm using right now.

Many thanks

Ahmed 

I can't write you a complete example, but if you look at the provided sample DLL\LoadLibrary you'll have 90% of it.  Perhaps you could even write this part of the application in VB - I have no experience calling Windows API routines from VB. The idea is to give you control over loading and unloading the DLL where you need variables reset.

Steve - Intel Developer Support

No problem at all

I will look at the provided examples and if there is any question I will let you know.

Many thanks

Ahmed

Hi Steve

I can not find such samples in my computer, Could you please help me to know where it is exist.

Many thanks

Ahmed

Find the folder where the compiler is installed - for example, C:\Program Files (x86)\Intel\Composer XE 2013 Under that is a Samples\en_US\Fortran folder. Unzip DLL.zip to your desktop or some other writable place (NOT under Program Files). You will find the DynamicLoad sample there (sorry, I had the name wrong.) It shows you how to load a DLL, call a routine in it, and unload it.

Steve - Intel Developer Support

Leave a Comment

Please sign in to add a comment. Not a member? Join today