最適化する関数が C# で記述されているときに、C# から r 統計最適化関数 (ここでは regnoud を使用したい) を呼び出すことができるかどうかを知りたいです。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 は、ネイティブ C/C++ DLL とは異なるマネージ DLL です。非 .Net 言語から直接使用することはできないため、COM オブジェクトとして公開する必要があります。2 つの方法のいずれかでこれを行うことができます。
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 としてコンパイルしてください。頑張ってください!
私があなたの必要性を明確に理解していれば、R を呼び出す C# が C# を呼び出すという最適化の問題があります。
現在、 R.NETでコールバック関数 (「関数ポインター」、「デリゲート」は通話相手に応じて呼び出すことができるため) を設定する方法はないと思います。私は非常に似たようなニーズを持っている可能性が高く、時間を割り当てることができれば、将来これを R.NET に貢献する可能性があります。
一方、R から C# を呼び出して作業することが許容される場合、つまり R がアプリケーションのエントリ ポイントである場合は、rClr パッケージを使用して確実に実行できます。C# で記述されたモデルの最適化と MCMC 分析を行っている同僚がいます。1 つのチュートリアルは、C# を使用した R からの最適化の非常に単純化された現実的なケースです。
http://www.codeproject.com/Articles/25819/The-R-Statistical-Language-and-C-NET-Foundations
このようなものをチェックしてください。今は C# についてあまり知らないので、私が不可能なことを言ったとしても、私を傷つけないでください:
最適化する関数を C# の文字として保存し、この StatConnector ライブラリを使用して R に送信してみてください (経験は限られています)。方程式を R 内で「z」として保存したとしましょう。変数の 1 つとして「get(z)」を使用して R スクリプトを呼び出します。