The t-test as a COM service

The Server

Here we define a simple COM server that has just two methods. The first is a wrapper around the t.test function. The second allows clients to generate a sample from Normal distribution. As usual, we combine the two methods into a list of functions and create a COM class definition using the the function SCOMFunctionClass.
def = SCOMFunctionClass(list(ttest = function(x, ...) t.test(as.numeric(x),...), rnorm = rnorm), name = "R.TTest")
def@classId = getuuid("11D2A4BC-7EBC-4236-80FF-2588EFCD8821")
And next, we register the definition with R and the Windows registry so that it is now available to clients.
registerCOMClass(def, registry = TRUE)
Note that in this case, we are providing a list of functions directly. This differs from the Normal distribution server in Sobject. In that case, the list of functions used in a COM instance needed to share an environment, and a separate one for each COM instance. As a result, there we used the SCOMIDispatch to define the COM class. Here we use SCOMFunctionClass which takes the list of functions directly.


Now we are ready to use this from a client. Our example will use Perl. We start by creating an instance of the COM class.

# Call with ActiveState Perl

use Win32::OLE;

$t = Win32::OLE->new("R.TTest") || die "Can't create R.TTest COM object";

Next, we call the ttest with data stored in Perl.

# Following currently is transferred as a list in S, not a numeric.
@x = (0.2795290,  1.2010954, -0.1396027,  0.1742421, -2.1921724 , 0.4139593, -0.3025258, -0.1818093,  0.6793734,  0.7978106);

$val = $t->ttest(\@x);

The result is an S object of class htest. The converter mechanism in the RDCOMServer uses the default mechanism for exporting these non-primitive objects and returns another COM object which provides access to all of the fields and attributes of this object and also allows one to call top-level S functions with this object as the first argument. Note how we get the statistic, parameter and estimate values as if they were regular properties of the COM or Perl object.

print "Result: $val\n";

$x = $val->statistic;
$d = $val->parameter;
$mean = $val->estimate;
print "Statistic: $x ($d) $mean\n";

Now, let's use the rnorm to generate data in the server, transfer it back to the client and then pass that back to the server in the call to ttest. (The round trips of the data can be avoided if we designed the COM object to have state and store the data locally. This is a very different idea, sometimes useful and sometimes not.)

print "Next stage\n";

# Now we create a second COM object within S and 
# use it to generate

$normal = Win32::OLE->new("SNormal");
@data = @{$normal->sample(100)};

$val = $t->ttest(\@data);

$x = $val->statistic;
$d = $val->parameter;
$mean = $val->estimate;
print "Statistic: $x ($d) $mean\n";