Reputation: 71
I want to know if it's possible to call r statistics optimization function (here I want to use regnoud) from C# while the function to be optimized is written in C#. I found RDotNet library but with it i cannot evaluate the C# function from R. In other terms, the problem is that R while optimizing needs to evaluate the function but he cannot do it because the function is in the C# code.
is there any solution like using .dll or other libraries?
thanks.
Upvotes: 6
Views: 4070
Reputation: 1539
If I understand your need clearly, you have a an optimisation problem with a C# calling R calling back C#.
I do not think there is a way to set up a callback function ("function pointer", "delegate" as they can be called depending on who you talk to) in R.NET currently. I am likely to have very similar needs and may contribute this to R.NET in the future, if I can allocate the time.
Meanwhile, if it is acceptable to have things such that you work from R calling C#, i.e. R is the entry point of your application, this is definitely doable using the rClr package. I have colleagues doing optimisation and MCMC analysis of a model written in C#. One tutorial is a very simplified but realistic case of optimisation from R using C#.
Upvotes: 1
Reputation:
I have done this before using a somewhat convoluted approach but it works!
First, you will need to create a C# DLL containing your function. You can do this in visual studio by selecting "class library" as the option when creating a new project. The code in the .cs file should look like this
namespace MyNamespace
{
//expose an interface with functions to be called from R
public interface MyInterface
{
string MyFunction(string name);
}
//create a class that implements the above interface
public class MyClass : MyInterface
{
public string MyFunction(string name)
{
return "Hello " + name;
}
}
}
Now compile your project and you will get a C# DLL. This DLL is a managed DLL which is different from a native C/C++ DLL. It cannot be directly consumed from non .Net languages and so needs to be exposed as a COM object. You can do this in one of two ways
The COM registration process will now have created a .tlb file in the same folder as your DLL. Keep this .tlb file. We will need it in the next step
The next step is to create a C++ DLL which can call the COM DLL. This step is needed because R can call a C++ DLL directly but cannot call COM directly (correct me if I am wrong or skip this step if you know a better way to call COM from R). The code for the C++ DLL in dllmain.cpp is shown below (make sure to scroll to see the full code)
#include "stdafx.h"
#include <iostream>
//import the .tlb file create by COM registration
#import "path_to_Dll\MyDll.tlb" named_guids raw_interfaces_only
void _cdecl MyCPPFunction(char ** strName)
{
//Initialize COM
HRESULT hr = CoInitialize(NULL);
//create COM interface pointer
MyNamespace::MyInterfacePtr myPtr;
//create instance of COM class using the interface pointer
HRESULT hr2 = myPtr.CreateInstance(MyNamespace::CLSID_MyClass);
//create variable to hold output from COM.
BSTR output;
//call the COM function
myPtr->MyFunction(_bstr_t(strName[0]), &output);
//convert the returned BSTR from .net into char*
int length = (int) SysStringLen(output);
char *tempBuffer;
tempBuffer = (char *) malloc(1 + length);
WideCharToMultibyte(CP_ACP, 0, output, -1, tempBuffer, length, NULL, NULL);
tempBuffer[length] = '\0';
//release interface
myPtr->Release();
//uninitialize COM
if(hr == S_OK)
CoUninitialize();
//set output in input for returning to R (this is weird but the only way I could make it work)
strName[0] = tempBuffer;
}
Now compile your project and you will get a C++ DLL. We are almost there now! Dont give up yet :). Now, you have a C# DLL exposed as a COM object and a C++ DLL that can call this COM object. The final step is to call the C++ function from R. Here is the R code to do that
#load C++ DLL
dyn.load("path_to_C++_DLL")
#call function in C++ DLL and pass in a test name.
# The C++ DLL will in turn call the C# function
output <- .C("MyCPPFunction", as.character("Peter"))
#print output
print(output)
And you should see "Hello Peter" displayed from C# in the R console! One very important point to note.
Always, compile the COM DLL using "any CPU" option. Always compile the C++ DLL to match your R installation! For example, if you have 32 bit R installed, then make sure you compile the C++ DLL as 32 bit DLL. If you have 64 bit R installed and want to use it, then make sure you compile your C++ DLL as a 64 bit DLL. Best of luck!
Upvotes: 12
Reputation: 513
http://www.codeproject.com/Articles/25819/The-R-Statistical-Language-and-C-NET-Foundations
Check out something like this. Now I don't know much about C# so if I say anything that is impossible please don't hurt me:
Try to save the function that you want optimized as a character in C#, and send it to R using this StatConnector library (I have some limited experience with it.) Let's say you saved the equation as 'z' within R, you can then call your R scripts with 'get(z)' as one of the variables.
Upvotes: 0