我想知道是否可以从 C# 调用 r 统计优化函数(这里我想使用 regnoud),而要优化的函数是用 C# 编写的。我找到了 RDotNet 库,但我无法从 R 评估 C# 函数。换句话说,问题是 R 在优化时需要评估函数但他不能这样做,因为函数在 C# 代码中。
有没有像使用 .dll 或其他库这样的解决方案?
谢谢。
在使用有点复杂的方法之前,我已经这样做了,但它确实有效!
首先,您需要创建一个包含您的函数的 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。我们现在快到了!不要放弃:)。现在,您有一个作为 COM 对象公开的 C# DLL 和一个可以调用此 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。祝你好运!
如果我清楚地了解您的需求,那么您有一个 C# 调用 R 回调 C# 的优化问题。
我认为目前没有办法在R.NET中设置回调函数(“函数指针”、“委托”,因为它们可以根据您与谁交谈来调用)。如果我能分配时间,我可能有非常相似的需求,并且将来可能会为 R.NET 做出贡献。
同时,如果您可以接受从 R 调用 C# 的工作,即 R 是您的应用程序的入口点,那么使用rClr 包绝对是可行的。我有同事对用 C# 编写的模型进行优化和 MCMC 分析。一个教程是使用 C# 从 R 优化的一个非常简化但现实的案例。
http://www.codeproject.com/Articles/25819/The-R-Statistical-Language-and-C-NET-Foundations
看看这样的东西。现在我对 C# 了解不多,所以如果我说任何不可能的话,请不要伤害我:
尝试将要优化的函数保存为 C# 中的字符,然后使用此 StatConnector 库将其发送到 R(我对它的经验有限。)假设您将方程保存为 R 中的“z”,然后您可以使用“get(z)”作为变量之一调用您的 R 脚本。