5

COM呼び出しを介してRから.NET関数を呼び出すことが可能かどうか疑問に思っています。

ライブラリrcomではCOMオブジェクトの呼び出しが許可されているため、理論的には、COMオブジェクトとして公開されているすべての.NETアセンブリでこれが可能です。

簡単にするために、で.Reverse()関数を呼び出すことができるかどうかを確認します。この関数はSystem.Text、デフォルトで.NETFrameworkからCOMオブジェクトとして公開されています。

これは私がこれまでに試したことです:

  1. システム内のProgIDのリストを取得しました(C#コードへのリンクを参照)。これが私のシステムに関連するProgIDのリストです:

    ---start list of COM ProgID entries---
    <snip>
    System.SystemException -> mscoree.dll
    System.Text.ASCIIEncoding -> mscoree.dll
    System.Text.StringBuilder -> mscoree.dll
    System.Text.UnicodeEncoding -> mscoree.dll
    System.Text.UTF7Encoding -> mscoree.dll
    System.Text.UTF8Encoding -> mscoree.dll
    <snip>
    ---end list---
    
  2. このRコードは、COMオブジェクトとして公開されている.NET.dllをロードします。

    library('rcom')
    x <- comCreateObject("System.Text.ASCIIEncoding")
    
  3. それは間違いなくCOMオブジェクトを見つけます:

    x attr(、 "class") 1 "COMObject"

  4. .Reverse()私の質問は、このCOMオブジェクト内で関数を呼び出すにはどうすればよいですか?

アップデート

.NETでは、呼び出しは次のようになります。

    string x = "hello".Reverse();

それで、Rでは、呼び出しは?

アップデート

RがC#を呼び出す例については、スライド61の「Windows上のアプリケーションにRを埋め込む」の「 RがC#を呼び出す」を参照してください。

ProgIdこれはProjectName.ClassName.NETクラスからのものであることに注意してください。

4

3 に答える 3

3

Windows上のアプリケーションにRを埋め込むのスライド61から65の手順に基づいて、COMを介してRから.NETコードを正常に呼び出しました。

Rコードは次のとおりです。

# This is a once-off call.
install.packages("rcom")
library(rcom)
# This is a once-off call. See rcom user manual at:
# http://cran.r-project.org/web/packages/rcom/rcom.pdf
installstatconnDCOM() 

x <- comCreateObject("InteropSample.MyClass32")
comSetProperty(x,"Text","xxx")
comSetProperty(x,"Connector",comThis())
comInvoke(x,"DoCallback")

R内の出力は次のとおりです。

> DoCallback: xxxNULL

.NETクラスのC#コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

// Before running this, get rid of errors with "RCOMServerLib" by adding the rcom type library:
//
// Make sure everything is 32-bit (32-bit build in .NET, 32-bit run of Revolution R).
//
// Tick "Register for COM interop" in .NET project settings.
// 
// 1.Browse to "C:\Revolution\R-Enterprise-6.1\R-2.14.2\library\rcom\libs\i386>", then execute:
// C:\Revolution\R-Enterprise-6.1\R-2.14.2\library\rcom\libs\i386> C:\Windows\Microsoft.NET\Framework\v4.0.30319\regtlibv12.exe rcom_srv.tlb
// Registration of rcom_srv.tlb successful.
//
// 2. Add reference to "rcom_srv.tlb", this gets rid of errors for RComServerLib.
//    (browse to "C:\Revolution\R-Enterprise-6.1\R-2.14.2\library\rcom\libs\i386")
//
// 3. If we are using VS2012, this .NET assembly class will be automatically registered as COM server on build if we are using VS2012. If using VS2012, you must do this manually on the command line.
// 
// See:
// http://generally.wordpress.com/2006/07/28/exposing-your-net-assembly-through-com/
// http://www.inside-r.org/packages/cran/rcom/docs/comCreateObject

// In R:
// comCreateObject("InteropSample.MyClass32")
// comSetProperty(x,"Text","xxx")
// comSetProperty(x,"Connector",comThis())
// comInvoke(x,"DoCallback")

namespace COM___called_from_R
{
    [Guid("3ddfe021-a0c6-4218-a254-4fc4328c99a7"),
     InterfaceType(ComInterfaceType.InterfaceIsDual)]
    internal interface IMyComponent
    {
        RCOMServerLib.IStatConnector Connector { set; }
        string Text { set; }
        void DoCallback();
    }

    [Guid("133fee0e-9b32-4429-8a43-6e2a706a9beb"), ComVisible(true)]
    [ProgIdAttribute("InteropSample.MyClass32")]
    public class MyComponent : IMyComponent
    {
        private string mText;
        private RCOMServerLib.IStatConnector mConnector;

        public RCOMServerLib.IStatConnector Connector
        {
            set { mConnector = value; }
        }

        public string Text
        {
            set { mText = value; }
        }

        public string MyProperty;

        public void DoCallback()
        {
            if (mConnector != null)
            {
                mConnector.EvaluateNoReturn("cat(\"DoCallback: "
                                            + mText + "\")\n");
            }
        }
    }
}

ノート

  1. これが機能するためには、すべてが一貫して32ビット、または一貫して64ビットである必要があります。次の設定を使用して、32ビットモードで動作させました。

    • C#アセンブリ(32ビットに設定)。
    • Rのバージョン(32ビットモードでRevolution Rを使用しました)。
  2. Visual Studio 2012(VS2012)を使用している場合、.NETプロジェクト設定で[COM相互運用機能の登録]にチェックマークを付けるとC:\Windows\Microsoft.NET\Framework\v4.0.30319\regtlibv12.exe、コンパイル時にカスタム.NETクラスをシステム全体のCOMコンポーネントとして登録するために自動的に実行されます。ただし、Visual Studio 2010(VS2010)を使用する場合、自動的には実行されません。この設定で実行されるのは、.tlbファイルを作成することだけです(手動でregtlibv12.exe実行する必要があります)。regtlibv12.exe

  3. 「regtlibv12.exe-uMyComDLL.tlb」を呼び出すことにより、COMコンポーネントの登録を解除できます。

  4. プロジェクトをビルドし、VS2012が出力.dllを書き込めないと文句を言う場合、これはRが呼び出しのためにプロジェクトをロックしていることを意味しますx <- comCreateObject("InteropSample.MyClass32")。VS2012をコンパイルできるように.dllのロックを解除するには、Rを閉じ、C#をコンパイルしてから、Rを再起動します。

追加情報

  1. パッケージのRヘルプをrcom参照してください。
  2. については、ユーザーマニュアルをrcom参照してください。
  3. statconnWikiページを参照してください。
  4. R v2.15で動作しない場合は、Rv2.14で試してください。
于 2013-02-13T23:22:28.420 に答える
2

私はこの質問が古いことを知っています、私は将来の.Net/R開発者を助けるために私の経験を報告しています。

何を試しても参考にできませんでしたrcom_srv.tlb

への参照をC:\Program Files\R\R-2.15.3\library\rcom\libs\i386\rcom_srv.tlb追加できませんでした。ファイルにアクセスできること、およびファイルが有効なアセンブリまたはCOMコンポーネントであることを確認してください。

ここに画像の説明を入力してください

RCOMServerLibとSTATCONNECTORSRVLibの両方を使用しているこの記事を見つけました。

public STATCONNECTORSRVLib.StatConnectorClass rdcom = null;
//public RCOMServerLib.InternalConnectorClass rdcom = null; // Use 'rcom' for debugging

どちらも進歩できなかったので、最終的にはRcomServerLibなしで進歩しました。

namespace XYZ.dotNetProject_R
{
    [Guid("FA6F70DD-CDD0-4FF3-94BA-E2B94E68321D"),
    InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IDataHelper
    {
        string[,] GetdotNetProject2DArray(string code, DateTime fromDate, DateTime toDate);        
    }

    [ComVisible(true)]
    [ProgId("XYZ.dotNetProject_R")]
    public class DataHelper : IDataHelper
    {
        public string[,] GetdotNetProject2DArray(string code, DateTime fromDate = default(DateTime), DateTime toDate = default(DateTime))
        {

        }
    }
}

そして私はこれをR経由で呼びます:

# On some PC's it wont download the Package until you set it to use your IE Proxy Settings:
setInternet2(TRUE)
# This is a once-off call.
install.packages("rcom")
# This is a once-off call.
installstatconnDCOM()

#Resusable calls
> library('rcom')
Loading required package: rscproxy
> dll = comCreateObject("XYZ.dotNetProject_R")
> dll
<pointer: 0x2079002c>
attr(,"class")
[1] "COMObject"
> series = comInvoke(dll,"GetdotNetProject2DArray","abc123","2000-01-01","2010-01-01")
> series
    [,1]         [,2]                 
 [1,] "2000-01-01" "1236.1" 

COMはジェネリックスをサポートしていないので、単に文字列配列を返しました。Rは、文字列、日時、整数などの基本/プリミティブ.Netタイプのみをサポートしていることがわかりました。オブジェクト配列を返そうとすると失敗し、.Net呼び出しはRにNULLを返しました。

于 2013-03-27T22:11:32.957 に答える
1

よく一般的にあなたは使用しますcomInvoke

s <- comInvoke(x,"Reverse")

ただし、メソッドもメソッドSystem.Text.ASCIIEncodingもないstringためReverse、実行するには別のメソッドを選択する必要があります。

于 2013-02-13T21:10:35.080 に答える