statconn.NET

This section in the wiki will provide some basic information about statconn.NET

Overview

statconn.NET is a .NET class library. It can be used in applications or plug-ins built with .NET 2.0 or newer (up to 4.0 is tested) in any of the managed languages (e.g. C# or Visual Basic.NET).

statconn.NET integrates statconnDCOM and/or statconnWS in a single .NET interface. Using any of the technology connectors

  • statconnDCOM (background server)
  • rcom via statconnDCOM (foreground server)
  • statconnWS

is made possible in statconn.NET without having to structure your application differently. Transparently integrate R into your application.

In addition to the types already known from statconnDCOM, statconn.NET supports data frames composed of all supported types (both getting or setting data).

Features

  • transparently integrate R into your application using statconnDCOM or statconnWS
  • R may run on a Linux or MacOS machine (using statconnWS)
  • data frames supported
  • multithreaded application support including synchronized access to R
  • easier debugging with additional debugging information without fiddling around with character devices as in statconnDCOM

Requirements

  • .NET framework 2.0, 3.0, 3.5 or 4.0
  • statconnDCOM or statconnWS or rcom with statconnDCOM

Examples

The following examples will show some facets of statconn.NET. The examples are only code snippets and not fully working solutions, but you can Cut&Paste to your own code.

All examples are in C#.

Using the Background Server

using statconn.NET;

...

  StatConnector.DefaultLicensee = "MyCompany";
  StatConnector lConnector = NewBackgroundConnector("R")
  lConnector.EvaluateNoReturn(...);

Using Data Frames

  DataFrame lDataFrame = (DataFrame) lConnector.GetSymbol("mydf");
  
  // add 1 to all elements in column 3 (zero-based index)
  for(int i=0;i < lDataFrame.GetRowCount(); i++)
  {
    lDataFrame.SetElement(i,3,lDataFrame.GetElement(i,3) + 1);
  }
  lConnector.SetSymbol("mydf",lDataFrame);

Error Handling

  try
  {
    lConnector.EvaluateNoReturn(...);
    lConnector.EvaluateNoReturn(...);
    lConnector.EvaluateNoReturn(...);
    lConnector.EvaluateNoReturn(...);
  }
  catch (Errors.SCException pException)
  {
    // ErrorCode contains the numeric error code
    // DebugInfo what the interpreter (R) will tell you about this
    // example: Error Code: 0x8004000b (evaluation stopped)
    //          Debug Info: "variable 'b' not found"
    System.Console.WriteLine("error code: "
                             + pException.ErrorCode.ToString()
                             + " // debug info: "
                             + pException.DebugInfo);
   
  }

Processing a Set of Statement

// this function contains a set of statements which must not
// be interrupted by any other calls to R (even from different
// threads!)
public void MyCode(StatConnector pConnector, object pParam)
{
  MyClass lObject = (MyClass) pParam;
  pConnector.SetSymbol(...);
  pConnector.EvaluateNoReturn(...);
  pParam.result = pConnector.Evaluate(...);
}

...

  // call MyCode, it must never be interrupted by any other
  // calls to R!
  MyClass lDataObject = new MyClass();
  lConnector.SyncRun(MyCode,lDataObject,null);
  // do something with the result
  x = lDataObject.result;

Asynchronous Processing a Set of Statement

// this function contains a set of statements which must not
// be interrupted by any other calls to R (even from different
// threads!)
private void MyCode(StatConnector pConnector, object pParam)
{
  MyClass lObject = (MyClass) pParam;
  pConnector.SetSymbol(...);
  pConnector.EvaluateNoReturn(...);
  pParam.result = pConnector.Evaluate(...);
}

// this function shall handle the results, will synchronize with the
// rest of the app _after_ asynchronous processing
private void MyCodeDone(StatConnector pConnector,object pParam)
{
  MyClass lObject = (MyClass) pParam;
  x = lObject.result;
}

...

  // call MyCode, it must never be interrupted by any other
  // calls to R!
  MyClass lDataObject = new MyClass();
  IAsyncResult lRun = lConnector.AsyncRun(MyCode,lDataObject,MyCodeDone);

  // do something else
  ...
  
  // sync point!
  lRun.AsyncWaitHandle.WaitOne();
  
  // now we know, MyCode is done and MyCodeDone has handled the results

Multithread it!

// this function contains a set of statements which must not
// be interrupted by any other calls to R (even from different
// threads!)
private void MyCode(StatConnector pConnector, object pParam)
{
  MyClass lObject = (MyClass) pParam;
  pConnector.SetSymbol(...);
  pConnector.EvaluateNoReturn(...);
  pParam.result = pConnector.Evaluate(...);
}

// second piece of R code, should run in parallel to the first one
private void MyOtherCode(StatConnector pConnector, object pParam)
{
  ...
}

// this function shall handle the results, will synchronize with the
// rest of the app _after_ asynchronous processing
private void MyCodeDone(StatConnector pConnector,object pParam)
{
  MyClass lObject = (MyClass) pParam;
  x = lObject.result;
}

// handle the results of the second code chunk
private void MyCode2Done(StatConnector pConnector,object pParam)
{
  ...
}

...

  // run two pieces of code in parallel in two instances of R
  StatConnector lConnector = NewBackgroundConnector("R");
  StatConnector lConnector2 = NewBackgroundConnector("R");
  
  // setup
  MyClass lDataObject = new MyClass();
  MyClass2 lDataObject2 = new MyClass2();
  
  // start processing: asynchronous processing in two background threads!
  IAsyncResult lRun1 = lConnector.AsyncRun(MyCode,lDataObject,MyCodeDone);
  IAsyncResult lRun2 = lConnector2.AsyncRun(MyCode2,lDataObject2,MyCode2Done);

  // sync point: we wait for both threads to finish their jobs!
  lRun1.AsyncWaitHandle.WaitOne();
  lRun2.AsyncWaitHandle.WaitOne();
  
  // now we know, both threads have done their job!

Personal Tools