- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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,
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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.
コピーされたリンク
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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.
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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.
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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.
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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.
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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)
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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,
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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.
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Thank you Michael and Steve!
That helped a lot.
