0% found this document useful (0 votes)
243 views

Using Pmlnet: 12 Series

This document discusses how to customize PDMS/Marine using PMLNet and .NET. It describes how .NET classes can expose functionality to PML via events and methods. Limitations include not being able to directly call PML from .NET. The document also covers topics like importing assemblies, passing arguments between PML and .NET, and attribute usage for PML callable classes.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
243 views

Using Pmlnet: 12 Series

This document discusses how to customize PDMS/Marine using PMLNet and .NET. It describes how .NET classes can expose functionality to PML via events and methods. Limitations include not being able to directly call PML from .NET. The document also covers topics like importing assemblies, passing arguments between PML and .NET, and attribute usage for PML callable classes.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

Using PMLNet Page 1 of 7

User Guide .NET Customisation 12 Series


Chapter: PMLNet

Using PMLNet
The diagram below shows how PDMS/Marine may be customised using PMLNet. A number of .NET API's are
available which allow access to the current database session, drawlist, geometry and other functionality.
Users are able to write their own managed code which accesses PDMS/Marine via these C# API's. It is not
possible to directly call PML from C#. However there is an event mechanism which allows PML to subscribe to
events raised from C# (these are shown in dashed lines below). Events are also raised when the database
changes and can be subscribed to from C# (also shown in dashed lines). In this example the external C#
assemblies share the same database session as Design i.e. they run in the same process and therefore see
the same data.

Limitations
• Only .NET classes which are marked as PMLNetCallable and adhere to certain rules can be called from
PML (these rules are described later)
• Module switching does not persist .NET objects. Core PML objects defined in FORTRAN or C++ are not
persisted either.
• Passing other PML system/user objects to .NET e.g. DIRECTION, ORIENTATION, … is not possible. It is
possible to pass database references to .NET either as an array or String. It is also possible to pass an
existing instance of a PML Net Proxy to .NET.
• It is not possible to call directly PML objects from .NET. The only way to call PML from .NET is via events.
• It is not possible to enter 'partial' namespaces as you might in C# and expect them to be concatenated.
E.g. the sequence:
USING NAMESPACE ‘Aveva.PDMS’
!netobj = object namespace.NETObject ( )
will give an error.
Objects and Namespaces
In order to identify and load a particular class definition the PML proxy class is assumed to have the same
name as the .NET class (PML callable classes must be case independent). This class name is passed to the
PMLNetEngine which creates the .NET instance e.g.
!a = object netobject()
creates an instance of the .NET class netobject. To specify in which assembly this class is defined and resolve

mk:@MSITStore:C:\AVEVA\Plant\PDMS12~1.SP4\DOCUME~1\NCUG.chm::/NCUG5.6... 6/3/2020
Using PMLNet Page 2 of 7

any name clashes the user needs to also specify the namespace in which the .NET class is defined using the
following syntax:
USING NAMESPACE <string>
Where <string> is the namespace in which the class is defined.
e.g. 'AVEVA.PDMS.PMLNetExample'
The namespace is considered to be case independent. This namespace will remain current until it goes out of
scope (e.g. at end of macro). When the user types:
!netobj = object NetObject ( )
then all namespaces in the current scope will be searched to find a match. In this example, if 'Aveva.PDMS.
PMLNetExample' is not currently in scope, then the error:
(46,87) PML: Object definition for NETOBJECT could not be found.
will be raised.
Object Names
Object names can consist of any alpha but not numeric characters (this restriction is imposed by PML). They
are treated as case-independent. However, it is no longer necessary to define them in upper case - any
mixture of upper and lower case letters will have the same effect.
Query Methods
The query methods on an object have been enhanced as follows:
(a) Querying an object will show the namespace name as well as the object name:
e.g.
q var !x

< AVEVA.PDMS.NAMESPACE.NETOBJECT>
AVEVA.PDMS.NAMESPACE.NETOBJECT
(b) There is a new query method to list all the methods of an object (including constructors)
Q METH/ODS
e.g.
q meth !x

<AVEVA.PDMS.NAMESPACE.NETOBJECT>AVEVA.PDMS.NAMESPACE.NETOBJECT
NETOBJECT ( )
NETOBJECT (REAL)
ADD (REAL)
REMOVE(REAL)
ASSIGN(AVEVA.PDMS.NAMESPACE.NETOBJECT)
DOSOMETHING(REAL, REAL, REAL)
Note that query methods will not list the methods on objects of type ANY, even though such methods are
available on all objects.

(c) A new query:


Q NAMESP/ACES
lists the namespaces currently in scope.
Global Method
There is a new global method on all objects:

mk:@MSITStore:C:\AVEVA\Plant\PDMS12~1.SP4\DOCUME~1\NCUG.chm::/NCUG5.6... 6/3/2020
Using PMLNet Page 3 of 7

.methods()
which returns a list of the methods on the object as an array of strings.
e.g.

!arr = !x.methods()
q var !x

returns:

<ARRAY>
[1] <STRING> 'NETOBJECT ( )'
[2] <STRING> 'NETOBJECT (REAL)'
[3] <STRING> 'ADD (REAL)'
[4] <STRING> 'REMOVE(REAL)'
[5] <STRING> 'ASSIGN(AVEVA.PDMS.NAMESPACE.NETOBJECT)'
[6] <STRING> 'DOSOMETHING(REAL, REAL, REAL)'
Importing an assembly
Before an instance of a .NET object can be instantiated the assembly containing the class definition must be
loaded. This is done using the IMPORT syntax as follows

IMPORT <string>

Where <string> is the case-independent name of the assembly


Method Arguments
Only PML variables of the following types may be passed to methods on .NET classes. In the table below the
PML variable type is in the left column and the .NET equivalent variable type is in the right column. Data is
marshalled in both directions between PML and .NET by the PMLNetEngine.
PML .NET
REAL double

STRING string

BOOLEAN bool

ARRAY (these can be sparse Hashtable


and multi-dimensional)

OBJECT Any existing PML Net PMLNetCallable class


instance
Arguments to PML Proxy methods are passed by reference so can be in/out parameters (in .NET output
arguments must be passed by reference).
Value Semantics
PML Gadgets and DB elements have reference semantics when they are copied whereas all other objects
have value semantics when they are copied. This is controlled by the Assign() method on the .NET class. So,
for example if the Assign() method here copies the value then

!a = object netobject()

mk:@MSITStore:C:\AVEVA\Plant\PDMS12~1.SP4\DOCUME~1\NCUG.chm::/NCUG5.6... 6/3/2020
Using PMLNet Page 4 of 7

!a.val(1)
!b = !a
!b.val(2)
then
q var !a.val() returns 1
and
q var !b.val() returns 2

i.e. !a and !b do not point to the same object.


In order to perform either a shallow or deep copy of the member data inside the .NET class the Assign()
method must be defined on the Net class (see rules). This is analogous to overriding the operator "=" in C++.
Method Overloading
Overloading of methods is supported for all variable types in PML so a .NET Proxy can be created from
a .NET class which has overloaded methods.
Custom Attributes
The custom attribute [PMLNetCallable()] is used to describe the PML interface for a .NET class. This
metadata allows the PML callable assemblies to be self-describing. This clearly defines the class and allows
an assembly to expose a subset of its public interface to PML. The PMLNetEngine uses this metadata to
decide which .NET class definitions can be created in PML. Reflection is used to load an assembly and create
PML class definitions. All classes and methods for which PML Proxy class definitions will be created must be
marked as PMLNetCallable. The assembly itself must also be marked as PMLNetCallable.
So, a PML callable .NET class in C# looks like this:
[PMLNetCallable()]
namespace PMLNet
{
[PMLNetCallable ()]
public class PMLNetExample
{
[PMLNetCallable ()]
public PMLNetExample()
{
}
[PMLNetCallable ()]
public void DoSomething(double x, double y, double z)
{
z = x + y;
}
}
}
This class has a default constructor and a single method. Both the constructor and method are marked as
PMLNetCallable along with the class itself.
The assembly itself must also be marked as PMLNetCallable. This is normally done in the AssemblyInfo file
as follows
using Aveva.PDMS.PMLNet;

[assembly: PMLNetCallable()]
Private Data and Properties
In PML there is no concept of private members or methods - everything is public. Access to public data
in .NET must be via properties or get/set accessor methods. Properties in .NET class are defined as get and
set methods in PML. So, for example the following PMLNetCallable property in .NET
[PMLNetCallable()]
public double Val
{
get

mk:@MSITStore:C:\AVEVA\Plant\PDMS12~1.SP4\DOCUME~1\NCUG.chm::/NCUG5.6... 6/3/2020
Using PMLNet Page 5 of 7

{
return mval;
}
set
{
mval = value;
}
}
would have the following Proxy methods in PML
REAL VAL()
VAL(REAL)
Scope
PML variables are of two kinds: global and local. Global variables last for a whole session (or until you delete
them). A local variable can be used only from within one PML function or macro. The lifetime of the .NET
instance is controlled by the scope of the PML proxy.
Instantiation
Classes can have any number of overloaded constructors but must have a default constructor which is
marked as PMLNetCallable. The PML Proxy constructor instantiates an instance of the underlying .NET class.
When the proxy goes out of scope the destructor destroys the underlying .NET instance.
ToString() Method
The string() method is available on all PML objects. For a .NET Proxy this will call the ToString() method on
the .NET instance. If the ToString() method is overridden on the .NET class then this will be called.
Method Names
PML is case independent, so it is not possible to have MyMethod() and MYMETHOD() in .NET. PML will
report non-unique object/method names.
Double Precision
Doubles are used in PMLNet to store reals and ints so doubles must be used in .NET (integers are not
available in PML)
Events
Events on PMLNet objects may be subscribed to from PML. A PML callback on a particular instance may be
added to an event on another PMLNet instance. Events are defined by a .NET component by associating the
delegate PMLNetEventHandler with the event. This delegate has the signature
__delegate void PMLNetEventHandler(ArrayList __gc *args);
Where args is an array of event arguments of any PMLNet type (see table of valid types). The following code
associates this delegate with an event
[PMLNetCallable()]
public class PMLNetExample
{
[PMLNetCallable()]
public event PMLNetDelegate.PMLNetEventHandler PMLNetExampleEvent;

[PMLNetCallable()]
public PMLNetExample ()
{
}

[PMLNetCallable()]
public void Assign(PMLNetExample that)
{
}

[PMLNetCallable()]
public void RaiseExampleEvent()
{
ArrayList args = new ArrayList();

mk:@MSITStore:C:\AVEVA\Plant\PDMS12~1.SP4\DOCUME~1\NCUG.chm::/NCUG5.6... 6/3/2020
Using PMLNet Page 6 of 7

args.Add("PMLNetExampleEvent ");
args.Add("A");
if (PMLNetExampleEvent!= null)
PMLNetExampleEvent(args);
}
}
This event can then be caught in PML by adding an appropriate callback to the instance raising the event
!n = object pmlnetexample()
!c = object netcallback()

!handle = !n.addeventhandler('pmlnetexampleevent', !c, 'callback')


Where
• !n is the PMLNet instance on which the event will be raised
• !c is the instance of a PML object with a method callback() with the appropriate arguments
At some later time the event handler may be removed
!n.removeeventhandler('pmlnetexampleevent', !handle)
where !handle is the handle of the PMLNet delegate returned by addeventhandler().
Netcallback is a PML object defined as
define method .callback(!array is ARRAY)
!args = 'NETCALLBACK object ' + !array[0] + !array[1]
$P $!args
endmethod
Error Handling
Exception handling is placed around the Invoke method to handle .NET method invocation exceptions like
TargetException, ArgumentException etc. The result of catching such an exception is to ultimately return a
PMLError object from PMLNetProxy::Invoke() which results in a PML exception (1000,n) being thrown where
1000 is the module number for PMLNet. .NET can throw its own PML exceptions. The exception to throw is
PMLNetException. For example
throw new PMLNetException(1000, 1, "PMLNetExample Exception");
This may then be handled inside a PML macro i.e.

handle(1000,1)

endhandle

Any other exception within the loaded assembly itself is caught by the global exception handler inside
PDMS/Marine.
Rules for Calling .NET
Certain rules must be adhered to when defining a .NET class which is PML callable. These are enforced by
the PMLNetEngine when an assembly is imported. They are
• PML callable assemblies must be marked as PMLNetCallable and reside in the %PDMSEXE% directory,
subdirectory of the application or UNC path.
• Only classes may be PML Callable (this excludes Structures, Interfaces, Enums, …).
• A PML callable class must be marked as PMLNetCallable.
• A PML callable method must be marked as PMLNetCallable.
• A PML callable method can only pass valid argument types (see table of types).
• PML callable classes and methods must be public.
• PML callable methods with default arguments cannot be defined.
• PML callable class and method names must be case independent.

mk:@MSITStore:C:\AVEVA\Plant\PDMS12~1.SP4\DOCUME~1\NCUG.chm::/NCUG5.6... 6/3/2020
Using PMLNet Page 7 of 7

• PML callable classes must have an Assign() method.


• PML callable classes must have a public default constructor which is PMLNetCallable.
If these rules are not adhered to then errors are reported to the trace log when the assembly is loaded and a
PML class definition will not be created. If the class definition has not been defined then the following PML
error will result
(46,87) PML: Object definition for XXX could not be found.
Tracing
In order to output trace to a log file and the console window add the following lines to the exe's config file
<system.diagnostics>
<switches>
<add name="PMLNetTraceSwitch" value="4" />
</switches>
</system.diagnostics>
<appSettings>
<add key="PMLNetTraceLog" value="C:\temp\PMLNetTrace.log" />
</appSettings>
This will create the file PMLNetTrace.log in C:\temp and log all the valid class definitions as they are imported.

Copyright 1974 to current year. AVEVA Solutions Limited and its subsidiaries. All rights reserved.

mk:@MSITStore:C:\AVEVA\Plant\PDMS12~1.SP4\DOCUME~1\NCUG.chm::/NCUG5.6... 6/3/2020

You might also like