6

最適化する関数が C# で記述されているときに、C# から r 統計最適化関数 (ここでは regnoud を使用したい) を呼び出すことができるかどうかを知りたいです。RDotNet ライブラリを見つけましたが、R から C# 関数を評価できません。言い換えれば、問題は、最適化中に R が関数を評価する必要があるが、関数が C# コードにあるため実行できないことです。

.dll や他のライブラリを使用するような解決策はありますか?
ありがとう。

4

3 に答える 3

12

やや複雑なアプローチを使用する前にこれを行いましたが、うまくいきます!

まず、関数を含む 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 は、ネイティブ C/C++ DLL とは異なるマネージ DLL です。非 .Net 言語から直接使用することはできないため、COM オブジェクトとして公開する必要があります。2 つの方法のいずれかでこれを行うことができます。

  1. Visual Studio では、プロジェクトのプロパティに移動し、[アプリケーション] タブの [アセンブリ情報] ボタンをクリックして、[アセンブリ COM を表示する] チェックボックスをオンにします。
  2. または、.net インストール フォルダーにある regasm.exe を使用して、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" が表示されるはずです! 1 つの非常に重要な注意点。

常に、「任意の CPU」オプションを使用して COM DLL をコンパイルします。R のインストールに合わせて、常に C++ DLL をコンパイルしてください。たとえば、32 ビット R がインストールされている場合は、C++ DLL を 32 ビット DLL としてコンパイルしてください。64 ビット R がインストールされていて、それを使用したい場合は、C++ DLL を 64 ビット DLL としてコンパイルしてください。頑張ってください!

于 2013-07-10T16:19:32.743 に答える
1

私があなたの必要性を明確に理解していれば、R を呼び出す C# が C# を呼び出すという最適化の問題があります。

現在、 R.NETでコールバック関数 (「関数ポインター」、「デリゲート」は通話相手に応じて呼び出すことができるため) を設定する方法はないと思います。私は非常に似たようなニーズを持っている可能性が高く、時間を割り当てることができれば、将来これを R.NET に貢献する可能性があります。

一方、R から C# を呼び出して作業することが許容される場合、つまり R がアプリケーションのエントリ ポイントである場合は、rClr パッケージを使用して確実に実行できます。C# で記述されたモデルの最適化と MCMC 分析を行っている同僚がいます。1 つのチュートリアルは、C# を使用した R からの最適化の非常に単純化された現実的なケースです。

于 2013-09-06T02:22:29.317 に答える
0

http://www.codeproject.com/Articles/25819/The-R-Statistical-Language-and-C-NET-Foundations

このようなものをチェックしてください。今は C# についてあまり知らないので、私が不可能なことを言ったとしても、私を傷つけないでください:

最適化する関数を C# の文字として保存し、この StatConnector ライブラリを使用して R に送信してみてください (経験は限られています)。方程式を R 内で「z」として保存したとしましょう。変数の 1 つとして「get(z)」を使用して R スクリプトを呼び出します。

于 2013-07-08T16:54:22.830 に答える