Planimate calling dotNET
Note On Notation
Support for dotNet will be provided by a Planimate callable DLL. The existing PL call DLL/API will be used initially with only minor changes to the API and the DLL calling notation within Planimate.
It has been proposed that DLL functions become as easy to use as regular routine operations (via enhancement of PL's routine editor and routine operation selection dialog). When this occurs the notation below will be simplified and further streamlining will be possible.
dotNET Interface DLL
A new DLL called PLCLR will give access to managed dotNET code. This DLL must be in Planimate's MDL or PBA directory. Unlike Planimate this DLL needs to be compiled with dynamic runtime libraries so it needs to remain separate.
Hence to use PLCLR, Visual Studio runtime distributables will need to be installed as well as dotNET. In the future compiling Planimate to use runtime distributables may become standard but it will impact PBA installation.
The DLL manages loading the dotNet Common Language Runtime (CLR) and the allocation of multiple objects during a Planimate session.
You start by initialising the DLL with a dotNet version ("" == latest installed).
p.result = PLCLR:Init("4.5")
You can explicitly unload the DLL and all loaded objects using PLCLR:Term().
The DLL can instantiate classes and will return a handle to them which is used to further work with them. The handle is an integer that can be stored in an attribute or table cell.
p.handle = PLCLR:New(dllname,classname,[...params]) p.result = PLCLR:Delete(p.handle)
You can call a method of a class as follows: p.result = PLCLR:Call(p.handle,"methodname",[...params])
You can call a getter/setter for a property directly: p.value = PLCLR:get("propertyName"); p.result = PLCLR:set("propertyName",p.value);
Translation between types will be handled similar to the SQLite DLL.
dotNET PL int/uint/long etc value (NearestInt) float value string text single array t.table.Column() 2D array table (TBD)
All Planimate date times will be translated to seconds since 1/jan/1970 and writes to PL dates will be auto-translated to the active epoch in Planimate.
Table data will be copied to arrays. A callback may enable access to data without copying it all (good for sparse access). I've not found out how to map unmanaged memory (PL table) so managed code can access it, yet.
Planimate can call a method which displays a modal dialog, with the method returning when the dialog closes. For dialog z-ordering, the main Planimate window handle (owner) will be passable as a parameter eg s.MainWindowHandle.
A single function will make modal dialogs easier, avoiding the need for separate New/Handle/Delete calls, but advanced users (eg: mutlitple complex properties to set) might still do it the long way.
p.result = PLCLR:ModalDialog("classname",params...)
A C# handler function "ModalDialog" will be expected to exist in the class. The Planimate window handle will automatically be passed to the constructor of the class. Params (as present) will be passed to the handler function.
Any standard dotNET form should work with a very small subclass to handle the parent window (TBD do it all in the PLCLR DLL).
A new paint object "Window" will enable a class to be instantiated within a window in a panel in Planimate. The window will receive show/hide messages when the panel it is on is shown/hidden and size messages if the paint object is anchored. A paint object property will give access to its window handle and will typically be passed via "New()" so a managed class can set it as its parent window.
PLCLR will have a flag that will enable it to catch all exceptions caused in managed code and display them in a dialog, passing the failure back to Planimate as an error so model development can continue instead of being closed by the managed code exception.
Beyond passing parameters, PLCLR will provide an API to C# virtually identical to the Planimate-As-A-DLL API, enabling managed code to call back Planimate to get/set data.
This will be particularly useful for modeless UIs.
TBD: merging PL Call DLL callbacks with PL as a DLL callbacks.