A COM interface to the S evaluator
We are used to using containers in other COM clients. For example, in
Excel the
Workbooks and the
Worksheets classes are containers for elements
of the class
Workbook and
Worksheet respectively. The container supports
a reasonably standard interface, providing properties/methods
Item,
Count,
Add and
Delete.
Now, suppose we want to implement a similarl concept in S. In our
case, we might create a general class definition for this and provide
the methods for any type of container.
COMContainerGenerator =
function(elementDefn) {
.containerElements = list()
newElement = function() {
.Call("R_RCOMSObject", elementDefn, PACKAGE = "RDCOMServer")
}
add = function() { # before, after, count, type
n = length(.containerElements)
tmp = newElement()
.containerElements[[n+1]] <<- tmp
tmp
}
count = function() {
length(.containerElements)
}
delete = function(which) {
.containerElements <<- .containerElements[-which]
TRUE
}
item = function(which) {
.containerElements[[which]]
}
list(Item = item, Delete = delete, Count = count, Add = add)
}
|
---|
We can use these generic methods to provide a container object in S.
We can define a COM container class for S that stores definitions
of particular container types.
setClass("SCOMContainerClass", representation("SCOMClass",
elementDefintion = "SCOMClass"))
|
---|
SCOMContainerClass =
function(elementDefn, name, help = "", def = new("SCOMContainerClass"), where = "")
{
def = .initSCOMClas(def, name = name, help=help)
def@elementDefinition = elementDefn
}
|
---|
Now we can define a method for
createCOMObject
that creates a container.
setMethod("createCOMObject",
"SCOMContainerClass",
function(def) {
funcs = COMContainerGenerator(def@elementDefinition)
obj = COMSIDispatchObject(funcs)
.Call("R_RCOMSObject", obj, PACKAGE="RDCOMServer")
})
|
---|
So now let's look at an example. Suppose we want to have a container
of elements of Normal distributions, e.g the SNormal class defined in
Sobject.xml. We will assume that this class is already
registered and that we know its UUID,
<uuid>c484d2f9-21f5-49ac-8c8d-2007e12245d3</uuid>.
edef = GetCOMClassDef("{c484d2f9-21f5-49ac-8c8d-2007e12245d3}"
def = SCOMContainerClass(edef, "NormalManager")
registerCOMClass(def)
|
---|
Now, clients can create instances of this container.
mgr = Win32::OLE->new("NormalManager");
%params = ('AB' => {0, 10}, 'CD' => {1, 3}, 'OK' = {-10, 2});
foreach $i keys($parms))
|
---|