我以前用了一种有点复杂的方法来做过这个,但是它有效!
首先,你需要创建一个包含你的函数的 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 文件。我们将在下一步中需要它。
下一步是创建一个C++ DLL,该DLL可以调用COM 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)
现在你应该从C#在R控制台中看到“Hello Peter”显示出来了!有一点非常重要。
始终使用“任何CPU”选项编译COM DLL。始终将C++ DLL编译为与您的R安装相匹配的版本!例如,如果您安装的是32位R,则确保将C++ DLL编译为32位DLL。如果您安装了64位R并想要使用它,请确保将C++ DLL编译为64位DLL。祝你好运!
http://www.codeproject.com/Articles/25819/The-R-Statistical-Language-and-C-NET-Foundations
看看类似这样的东西。现在我不太了解C#,所以如果我说了什么不可能的话,请不要伤害我:
尝试将您想要优化的函数保存为C#中的一个字符,并使用此StatConnector库将其发送到R。 (我有一些有限的经验)。假设您将等式保存为'R'中的“z”,则可以使用“get(z)”作为变量之一调用您的R脚本。