Using Pmlnet: 12 Series
Using Pmlnet: 12 Series
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.
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>
STRING string
BOOLEAN bool
!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
[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(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
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