Difference between revisions of "Planimate calling dotNET"

From Planimate Knowledge Base
Jump to: navigation, search
Line 1: Line 1:
 +
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.
 +
 
__TOC__
 
__TOC__
  
== Note On Notation ==
+
== PLCLR ==
 +
 
 +
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”)
  
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.
+
p.handle is a number that you'll need to work with the object. You can also use a table cell to store it.
  
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.
+
For future maintenance, its good form to put the strings into portal text attributes, literal text is used here to make the example clearer.
  
== dotNET Interface DLL ==
+
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.
  
A new DLL called PLCLR will give access to managed dotNET code. This DLL must be in Planimate's MDL or PBA directory.
+
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.
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.
+
p.result = PLCLR:Del(p.handle)
  
The DLL manages loading the dotNet Common Language Runtime (CLR) and the allocation of multiple objects during a Planimate session.
+
PLCLR will recycle handle values for deleted objects.
  
You start by initialising the DLL with a dotNet version ("" == latest installed).
+
== Calling Methods ==
  
  p.result = PLCLR:Init("4.5")
+
Lets say you c# class has a method:
  
You can explicitly unload the DLL and all loaded objects with:
+
public void SayHello()
 +
{
 +
  MessageBox.Show(“Hello”);
 +
}
  
p.result = PLCLR:Term()
+
You can call a method as follows:
  
== Class Instances ==
+
p.result = PLCLR:Call(p.handle,”SayHello”)
  
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.
+
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:
  
  p.handle = PLCLR:New(dllname,classname,[...params])
+
  public void ComplexCalculation(int value_in,out double value_out)
  p.result = PLCLR:Delete(p.handle)
+
  {
 +
  value_out = value_in + 0.5;
 +
}
  
You can call a method of a class as follows:
+
In Planimate you use
  
  p.result = PLCLR:Call(p.handle,"methodname",[...params])
+
  p.result = PLCLR:Call(p.handle,"ComplexCalculation(p.value1,p.value2)
  
You can call a getter/setter for a property directly:
+
Since value_out is declared as an "out", Planimate will set p.value p.value2 to the value calculated in the method.
  
  p.value = PLCLR:get("propertyName");
+
== Properties ==
  p.result = PLCLR:set("propertyName",p.value);
+
 
 +
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 p.name a portal attribute in text format, you can use:
 +
 
 +
  p.name = PLCLR:get("username");
 +
 
 +
and
 +
 
 +
  p.result = PLCLR:set("uername",p.name);
 +
 
 +
This also works for numbers, see the next section.
  
 
== Data Types ==
 
== Data Types ==
  
Translation between types will be handled similar to the SQLite DLL.
+
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.
 +
 
  
 
  dotNET                Planimate
 
  dotNET                Planimate

Revision as of 13:00, 29 June 2016

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

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()
{
 MessageBox.Show(“Hello”);
}

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.

Properties

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 p.name a portal attribute in text format, you can use:

p.name = PLCLR:get("username");

and

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

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.


dotNET                Planimate
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.

MODAL DIALOGS

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.

Exceptions

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.

Callbacks

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.