我想知道是否可以从C#调用r统计优化函数(这里我想使用regnoud),而要优化的函数是用C#编写的。 我找到了RDotNet库,但有了它我无法评估来自R的C#函数。 换句话说,问题在于R在优化时需要评估函数,但由于函数在C#代码中,因此无法执行。
是否有使用.dll或其他库的解决方案?
感谢。
答案 0 :(得分:9)
我在使用一种有点复杂的方法之前已经这样做了,但它确实有效!
首先,您需要创建一个包含您的函数的C#DLL。您可以在visual studio中通过选择“类库”作为创建新项目时的选项来执行此操作。 .cs文件中的代码应如下所示
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;
}
}
}
现在编译你的项目,你将得到一个C#DLL。此DLL是托管DLL,它与本机C / C ++ DLL不同。它不能直接从非.Net语言中使用,因此需要作为COM对象公开。您可以通过以下两种方式之一完成此操作
COM注册过程现在将在与DLL相同的文件夹中创建.tlb文件。保留此.tlb文件。我们将在下一步中使用它
下一步是创建一个可以调用COM DLL的C ++ DLL。这个步骤是必需的,因为R可以直接调用C ++ DLL但不能直接调用COM(如果我错了就纠正我,或者如果你知道从R调用COM的更好方法,则跳过这一步)。 dllmain.cpp中C ++ DLL的代码如下所示(确保滚动查看完整代码)
#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;
}
现在编译你的项目,你将获得一个C ++ DLL。我们差不多了!不要放弃:)现在,您有一个C#DLL公开为COM对象和一个可以调用此COM对象的C ++ DLL。最后一步是从R调用C ++函数。这是执行该操作的R代码
#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)
你应该在R控制台中看到C#中显示的“Hello Peter”!需要注意的一点非常重要。
始终使用“任何CPU”选项编译COM DLL。始终编译C ++ DLL以匹配您的R安装!例如,如果安装了32位R,请确保将C ++ DLL编译为32位DLL。如果您安装了64位R并想要使用它,那么请确保将C ++ DLL编译为64位DLL。祝你好运!
答案 1 :(得分:1)
如果我清楚地理解你的需要,你就会遇到一个C#调用R回拨C#的优化问题。
我认为有一种方法可以在R.NET当前设置一个回调函数(“函数指针”,“委托”,因为它们可以根据你的联系方式调用)。我很可能有非常相似的需求,如果我可以分配时间,可能会在未来为R.NET做出贡献。
同时,如果你可以使用R调用C#工作,即R是你的应用程序的入口点,那么使用rClr这绝对是可行的。 包。我让同事们对用C#编写的模型进行优化和MCMC分析。一个tutorial是使用C#从R优化的非常简化但实际的情况。
答案 2 :(得分:0)
http://www.codeproject.com/Articles/25819/The-R-Statistical-Language-and-C-NET-Foundations
查看类似的内容。现在我对C#了解不多,所以如果我说任何不可能的事情,请不要伤害我:
尝试将您想要优化的函数保存为C#中的字符,并使用此StatConnector库将其发送给R(我对它有一些经验。)假设您在R中将等式保存为“z”,然后,您可以使用'get(z)'作为变量之一来调用R脚本。