Adding Fortran subroutines to wxWindows GUI code
As mentioned in the mixed-languages notes, you may need to add a C++ graphical user interface to existing Fortran numerical codes. For the purposes of this note, we'll focus on using the cross-platform wxWindows toolkit, available for Windows and Unix platforms, with MacOS support coming soon. Currently, the wxWindows toolkit is only installed on GNU/Linux systems in the CAE Lab.
Program Structure and Code
We'll call FORTRAN subroutines as necessary from the C++ code, as documented in the mixed-languages notes. The C++ code is based on Robert Roebling's Hello, World tutorial. The only additions or changes include the following:
-
extern "C"declaration for FORTRAN subroutine, in the same form as shown in the mixed-language notes:extern "C" { void setab_(int *a, int *b); } - Addition of variables
length,a,b, andstatusinvolved in the creation of the status bar text:int length, a, b; char status[50]; - Replacement of a simple static
SetStatusText()call with:setab_(&a,&b); length=sprintf(status, "Welcome to wxWindows: a=%d, b=%d", a, b); if (length<=50) { SetStatusText(status); } else { SetStatusText("Welcome to wxWindows: a and b not set due to string overflow"); }
File hw-wx.C
Store the following code in the file 'hw-wx.C':
extern "C" {
void setab_(int *a, int *b);
}
#include "wx/wx.h"
class MyApp: public wxApp {
virtual bool OnInit();
};
class MyFrame: public wxFrame {
public:
MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size);
void OnQuit(wxCommandEvent &event);
void OnAbout(wxCommandEvent &event);
DECLARE_EVENT_TABLE()
};
enum {
ID_Quit = 1,
ID_About,
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Quit, MyFrame::OnQuit)
EVT_MENU(ID_About, MyFrame::OnAbout)
END_EVENT_TABLE()
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit() {
MyFrame *frame = new MyFrame( "Hello, World", wxPoint(50,50), wxSize(450,340) );
frame->Show(TRUE);
SetTopWindow(frame);
return TRUE;
}
MyFrame::MyFrame(const wxString &title,
const wxPoint &pos,
const wxSize &size):
wxFrame((wxFrame *)NULL, -1, title, pos, size) {
int length, a, b;
char status[50];
wxMenu *menuFile = new wxMenu;
menuFile->Append(ID_About, "&About...");
menuFile->AppendSeparator();
menuFile->Append(ID_Quit, "E&xit");
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menuFile, "&File");
SetMenuBar(menuBar);
CreateStatusBar();
setab_(&a,&b);
length=sprintf(status, "Welcome to wxWindows: a=%d, b=%d", a, b);
if (length<=50) {
SetStatusText(status);
}
else {
SetStatusText("Welcome to wxWindows: a and b not set due to string overflow");
}
}
void MyFrame::OnQuit(wxCommandEvent &WXUNUSED(event)) {
Close(TRUE);
}
void MyFrame::OnAbout(wxCommandEvent &WXUNUSED(event)) {
wxMessageBox("This is a wxWindows Hello World sample",
"About Hello World", wxOK | wxICON_INFORMATION, this);
}
File setab.f
Store the following code in the file 'setab.f':
subroutine setab(a,b)
integer a, b
a=3;
b=5;
return
end
Compilation Steps
Each program is compiled into an object file using the
appropriate compiler with the -c flag. After all the object files are created, the final g++ command links the object files together into a single executable:
mwr@ch208a:~/code/c++$ g++ -c hw-wx.C `wx-config --cxxflags`
mwr@ch208a:~/code/c++$ g77 -c setab.f
mwr@ch208m:~/code/c++$ g++ -o hw-wx-2 `wx-config --libs` hw-wx.o setab.o
Results
To run the program:
mwr@ch208a:~/code/c++$ ./hw-wx-2
