SimSoup has was originally developed using the Borland products C++ Builder and Kylix (C++). At various times, there was uncertainty over the future of these products.
In order to ensure that a development platform would continue to be available for SimSoup, I migrated the project to use the Lazarus open source product for the user interface, and C++ for the main simulation code.
Lazarus is an open source IDE and set of class libraries for Free Pascal that provides functionality very similar to Borland's Delphi GUI Builder product on Windows. It also provides similar features to the Linux based Kylix (Delphi) product. Lazarus therefore provides a potential migration path for projects curently based on Delphi or Kylix (Delphi).
I plan to document the migration approach in due course. In the meantime, here is a very brief outline. Source code is also available on the download page.
extern "C"
This applies both in the case of functions that are implemented in C++ (ie those that are called from Free Pascal) and functions that are implemented in Free Pascal (ie those that are called from C++). The Free Pascal code has to have an 'exports' section mentioning each of the Free Pascal functions / procedures that are called from C++.
As an example, the C++ declaration of TCheckbox looks like this:-
class TCheckBox: public TControl
{
public:
bool Get_Checked();
void Set_Checked(bool Checked);
};
The "public TControl" part means that it inherits many of its properties from TControl (which has a separate declaration)
Note that I have "Get_Checked()" and "Set_Checked()" functions rather than a "Checked" property as in C++ Builder. This entails modifications to the syntax of the C++ Builder code. I'm not sure whether it would have been possible to avoid this. Possibly I could have done something with C++ operator overloading. In any case I don't see it as a substantial problem. The syntactical changes required are very straightforward. It would have been far more difficult to make the changes required to use a different widget set.
My VCL Emulation classes only declare and implement a fairly small number of classes and methods corresponding to those parts of the user interface component library that I actually use. The basic technique is of course extendable, so that if I want to use a Component or method that I have not used before, I just have to add it to the VCL Emulation code.
function Laz_SimControl_Get_Action_Repeat_CheckBox_Ptr(Laz_Form_Ptr: TMainForm):TCheckBox; cdecl; // Return a pointer to the Simulation Control Action Repeat CheckBox begin Result := Laz_Form_Ptr.Action_Repeat_CheckBox; end;Once the C++ code has the pointer, it can then treat it as a pointer to a C++ object and call VCL Emulation functions for that object. For example, if the C++ code stores the result of the above function in CheckBox_Ptr, it can then say:-
CheckBox_Ptr->Set_Checked(true);to make the CheckBox checked.