是否有可能调用R统计函数来优化c#函数?

本文关键字:函数 优化 统计 有可能 调用 是否 | 更新日期: 2023-09-27 18:19:25

我想知道是否有可能从c#调用r统计优化函数(这里我想使用regnoud),而要优化的函数是用c#编写的。我找到了RDotNet库,但有了它,我无法从R中评估c#函数。换句话说,问题是R在优化时需要计算函数,但他不能这样做,因为函数在c#代码中。

是否有任何解决方案,如使用。dll或其他库?
谢谢。

是否有可能调用R统计函数来优化c#函数?

我以前使用过一种有点复杂的方法,但它有效!

首先,你需要创建一个包含函数的c# DLL。你可以在visual studio中通过选择"class library"作为创建新项目的选项来做到这一点。.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对象公开。您可以通过以下两种方式之一来实现

  1. 在Visual Studio中,你可以转到项目属性,点击"应用程序"选项卡下的"装配信息"按钮,并选中"使装配COM可见"复选框。
  2. 或者,你可以使用regasm.exe,它可以在。net安装文件夹中找到,将DLL注册为COM组件。这里有一个描述这个过程的链接。http://msdn.microsoft.com/en-us/library/tzat5yw6 (v = vs.71) . aspx。命令通常是"regasm myTest.dll/tlb:myTest.tlb"

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"!有一点很重要,

总是使用"any CPU"选项编译COM DLL。始终编译c++ DLL以匹配您的R安装!例如,如果您安装了32位的R,那么请确保将c++ DLL编译为32位DLL。如果你安装了64位的R并想要使用它,那么请确保将c++ DLL编译为64位的DLL。祝你好运!

如果我清楚地理解你的需求,你有一个优化问题,c#调用R调用c#。

我不认为有一种方法来建立一个回调函数("函数指针","委托",因为他们可以被调用取决于你与谁交谈)在r。net目前。我很可能有非常相似的需求,如果我能分配时间的话,将来可能会把它贡献给rnet。

同时,如果你可以接受从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脚本。