- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I have a C# based GUI that calls a FORTRAN-based dll. I would like to output a progress bar in the C#-GUI, but I'm not sure how that linkage would work. I know it can be done using the Dialog Box feature in Intel Visual Fortran with Microsoft Visual Studio, but that wouldn't show in my developed C#-GUI.
Any ideas or references?
Thanks,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have done very little with C#, but given that you are using a Fortran DLL what I recommend is that, in the call to the DLL, you include a pointer to a callback routine (in C#). The Fortran code would accept this as a TYPE(C_FUNPTR) and you would then use C_F_PROCPOINTER (both of these are defined in intrinsic module ISO_C_BINDING) to convert it to a Fortran procedure pointer. Then at the appropriate times in the Fortran code, call the C# routine through the procedure pointer to update the progress bar.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Pass the Fortran DLL routine a pointer to a C-interoperable procedure that the Fortran DLL can call back periodically to update the progress bar.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I would recommend leaving all the GUI work to C# code and implement some sort of callback mechanism for "% complete" from Fortran DLL to C#. Mixing of different GUI implementations is possible (after all, they all end up being OS windows with window handles), but would be prone to lots of weird problems.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am not sure which API you are using (WPF vs Forms). If you are using WPF, you need to be very careful as WPF runs on a single thread. This means that you probably will need to create a new thread for your Fortran code - unless you do not mind interrupting your calculations. If you search WPF related forums you will find lots of examples:
https://stackoverflow.com/questions/15327717/algorithm-progress-callback
The other issue you have to deal with is to pass a reference to your progress bar from C# to FORTRAN which is not so trivial as far as I know.
You may like to look at creating DLLs wrapped in a managed C++ I posted yesterday. These problems become a little simpler.
i. konuk
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Ibrahim:
1. Do not waste your time.
2. Implement the update bar in Fortran -- it is not difficult
3. C# and Fortran are not designed to work together -- think the Iliad - C# is the Trojan Horse sent into the Fortran encampment and really just as welcome.
Although somewhere on this forum I posted a C# program that calls fortran.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is how I have done this using delegates:
C# Code
publc static class Fortran { public delegate bool ProgressHandler(int i, int n); [DllImport("fortran.dll")] internal static extern void TEST( double[] in_values, ... ProgressHandler update); } public bool UpdateProgress(int i, int n) { /* Set progress bar here */ } public void CallFortran() { Fortran.TEST( in_values, .. UpdateProgress); }
and the corresponding Fortran code
SUBROUTINE TEST( & in_values, & ... update) !DEC$ATTRIBUTES ALIAS:'TEST' :: TEST !DEC$ATTRIBUTES DLLEXPORT :: TEST !DEC$ATTRIBUTES VALUE :: n IMPLICIT NONE !----------------------------------------------------------------------- ! Specifications for passed arguments !----------------------------------------------------------------------- INTEGER, intent(in) :: n REAL(8), intent(in) :: in_values(n) !----------------------------------------------------------------------- ! Specifications for passed function pointers !----------------------------------------------------------------------- interface FUNCTION update(i,n) result(ok) !DEC$ ATTRIBUTES VALUE :: i, n import integer, intent(in):: i, n LOGICAL :: ok END FUNCTION update END interface
The reason the handler returns a `bool`, is so that calls can support cancelation. The C# update function polls if the cancel button was pressed and Fortran checks the `ok` logical value returned from the callback.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Alternate suggestion have two entry points to the Fortran DLL. One to DoWork and the other to query progress. Then nstead of calling the Fortran function directly from C#, have C# spawn an additional C# thread that calls the Fortran DLL, then following the spawn of DoWork insert a loop that:
startDoWorkThread();
Done = false;
while(!Done)
{
SleepForSomeShortTime();
Done = QueryProgress(retProgress); // set Done when done, get progress in retProgress
UpdateProgressBar(retProgress);
}
The above is sketch code.
**** IIF the Fortran code itself is multi-threaded using OpenMP, then the worker thread you spawn from C# should be spawned only once and left around for re-use on subsequent calls into the DLL.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Progress bars are really easy from Fortran, no need for any of the complexity. If you have created a dialog with a progressbar element, all you need is to fetch the window handle for the progressbar. Here is a sample proc function for a dialog which contains a progress bar,
INTEGER FUNCTION StartupProc (hwnd, msg, wParam, lParam) RESULT (res) !DEC$ IF DEFINED(_X86_) !DEC$ ATTRIBUTES STDCALL, ALIAS : '_StartupProc@16' :: StartupProc !DEC$ ELSE !DEC$ ATTRIBUTES STDCALL, ALIAS : 'StartupProc' :: StartupProc !DEC$ ENDIF USE DlgDate USE comctl32 USE contwrap IMPLICIT NONE SAVE INTEGER(HANDLE), INTENT(IN) :: hwnd INTEGER(UINT), INTENT(IN) :: msg INTEGER(fWPARAM), INTENT(IN) :: wParam INTEGER(fLPARAM), INTENT(IN) :: lParam INTEGER :: rval INTEGER(HANDLE), SAVE :: hwndControl, hwprogressbar INTEGER :: controlId INTEGER :: code ! total delay of max_periods x period_delay, value in milliseconds INTEGER, SAVE :: period_count INTEGER, PARAMETER :: period_delay = 200, max_periods = 50 res = DefaultDialogProc (hwnd, msg, wParam, lParam) SELECT CASE (msg) CASE (WM_INITDIALOG) CALL InitCC (ICC_PROGRESS_CLASS) period_count = 0 rval = SetTimer (hwnd, 1, period_delay, NULL) ! delay in milliseconds CALL CheckBoxSetSelected (hwnd, IDC_DATAENABLE, .TRUE.) CALL CheckBoxSetSelected (hwnd, IDC_FLASHCLEAR, .FALSE.) hwprogressbar = GetDlgItem (hwnd, IDC_STARTUP_PB) rval = SendMessage (hwprogressbar, PBM_SETRANGE, 0, MakeLong(INT2(0), INT2(max_periods))) rval = SendMessage (hwprogressbar, PBM_SETPOS, 0, 0) rval = SendMessage (hwprogressbar, PBM_SETSTEP, 1, 0)
and when you want to advance the progress bar, send it a message,
rval = SendMessage (hwprogressbar, PBM_STEPIT, 0, 0)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
John Alexiou wrote:Here is how I have done this using delegates:
C# Code
publc static class Fortran { public delegate bool ProgressHandler(int i, int n); [DllImport("fortran.dll")] internal static extern void TEST( double[] in_values, ... ProgressHandler update); } public bool UpdateProgress(int i, int n) { /* Set progress bar here */ } public void CallFortran() { Fortran.TEST( in_values, .. UpdateProgress); }and the corresponding Fortran code
SUBROUTINE TEST( & in_values, & ... update) !DEC$ATTRIBUTES ALIAS:'TEST' :: TEST !DEC$ATTRIBUTES DLLEXPORT :: TEST !DEC$ATTRIBUTES VALUE :: n IMPLICIT NONE !----------------------------------------------------------------------- ! Specifications for passed arguments !----------------------------------------------------------------------- INTEGER, intent(in) :: n REAL(8), intent(in) :: in_values(n) !----------------------------------------------------------------------- ! Specifications for passed function pointers !----------------------------------------------------------------------- interface FUNCTION update(i,n) result(ok) !DEC$ ATTRIBUTES VALUE :: i, n import integer, intent(in):: i, n LOGICAL :: ok END FUNCTION update END interface
The reason the handler returns a `bool`, is so that calls can support cancelation. The C# update function polls if the cancel button was pressed and Fortran checks the `ok` logical value returned from the callback.
Hi John,
In which part of the code are the iterations run and get updated?
Thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Ret.) wrote:Pass the Fortran DLL routine a pointer to a C-interoperable procedure that the Fortran DLL can call back periodically to update the progress bar.
Mr. Lionel,
The counter is running inside the fortran dll and the GUI is developed by a C# code. The GUI calls the fortran dll one time to run the iterations. I'd like to get the current iteration number from the fortran dll while it's running and pass it to the C# code. Can you provide more information about that?
Thanks,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have done very little with C#, but given that you are using a Fortran DLL what I recommend is that, in the call to the DLL, you include a pointer to a callback routine (in C#). The Fortran code would accept this as a TYPE(C_FUNPTR) and you would then use C_F_PROCPOINTER (both of these are defined in intrinsic module ISO_C_BINDING) to convert it to a Fortran procedure pointer. Then at the appropriate times in the Fortran code, call the C# routine through the procedure pointer to update the progress bar.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ibraham,
Code for what Steve describes is shown here; I was the orginal poster albeit on another account: https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/391002
Let me know if you have any problems getting this working and I will do my best to help.
Regards,
Michael
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you Michael and Steve!
That helped a lot.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page