Planimate calling dotNET

From Planimate Knowledge Base
Revision as of 14:54, 29 June 2016 by Rick (talk | contribs) (Data Types)
Jump to: navigation, search

This describes Planimate's interface to the dotNET environment which gives access to a wide variety of modern UI elements, table editing and graphing libraries as well as libraries that easily interface to web APIs and databases.


PLCLR.DLL is a Planimate callable DLL which provides the interface to dotNET's Common Language Runtime. You'll see its name in all the calls to the API. In future versions the calls will be integrated and appear as internal Planimate routines.

PLCLR expects you to point it to dotNET DLLs (called Assemblies). All DLLs involved must be in the same folder as the MDL during editing and the PBA EXE for a PBA. In addition, users will need Visual Studio 2013 runtime libraries and dotNET 4.5 installed. These can be obtained from Microsoft. When shipping a PBA, an installer should check for these and install as required.

Creating Instances Of Classes

You start by creating an instance of a class written in C# (Windows Forms) or c# / XAML (WPF). The examples below assume you have access to the TestCLR model and WPFTest sample C# project.

To create an instance you need the DLL name and the class name including namespace, eg:

p.handle = PLCLR:New(“WPFTest.DLL”,”WPFTest.MainWindow”)

p.handle is a number that you'll need to work with the object. You can also use a table cell to store it.

For future maintenance, its good form to put the strings into portal text attributes, literal text is used here to make the example clearer.

You should test that p.handle is > 0 after a New. If its <= 0 an error occurred, in which case take away the negative (0 – p.handle) and you have the PLCLR error code.

When you've finished using an object you should dispose of it, though in some instances an object will persist the entire lifetime of the PBA so this is not necessary.

p.result = PLCLR:Del(p.handle)

PLCLR will recycle handle values for deleted objects.

Calling Methods

Lets say you c# class has a method:

public void SayHello()

You can call a method as follows:

p.result = PLCLR:Call(p.handle,”SayHello”)

Note the result of the call is always the result of PLCLR's operation, return values of methods are not used. Instead, you can pass parameters by value or reference, eg:

public void ComplexCalculation(int value_in,out double value_out)
 value_out = value_in + 0.5;

In Planimate you use

p.result = PLCLR:Call(p.handle,"ComplexCalculation(p.value1,p.value2)

Since value_out is declared as an "out", Planimate will set p.value p.value2 to the value calculated in the method.


If in your c# class you have a public property with a getter/setter eg:

String username  {get; set;}

Then you can use PLCLR's Get and Set operations to access them. With a portal attribute in text format, you can use: = PLCLR:get("username");


p.result = PLCLR:set("uername",;

This also works for numbers, see the next section.

Data Types

PLCLR has an extensible translation system to map between Planimate's simple data types and c#'s types. It matches the type of data passed in a parameter from Planimate with the type in a method's parameter or class property and chooses a translation as follows.

Conversions work for inputs to a method and outputs ("ref" or "out" parameters in C#) unless otherwise noted.

Parameter/Property Type Translation
dotNET Planimate Notes
double value (portal,routine,item/system attribute), table cell
int,uint value,cell Nearest Integer used
bool value,cell Nearest Integer then 0=false, nonzero=true
string Text attribute or cell Not label but you can use string expression to convert any format to text
double[], int[], uint[], boolean[] t.table.Column() Conversions above applied per cell
double[], int[], uint[] t.tablep[] Just column one sent with less overhead than Column(). Conversions above applied per cell. Row number changes on return supported.
string[] t.table.Column() Column must be a text column, currently cannot return data.
double[][] t.table[] Entire table's raw numbers, as array of columns, ie: array of array of numbers
Dictionary<String,int> l.labellist Label list mapped so elements are index values, keyed by name
Dictionary<int,String> l.labellist Label list mapped so elements are strings, keyed by their index value
string[] l.labellist Label list names sent as a array of Strings. In order of index but the index numbers are lost. If returned, a new list is created indexed from one. The labels must not be repeated.

Dates And Times

Currently all Planimate date/times are sent as the number of seconds since the model run start date. A future Datetime interface may be added. The PLEngine module can assist with conversion.


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 try do it all in the PLCLR DLL).

Modeless Dialog

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.