我想知道是否可以通过 COM 调用从 R 调用 .NET 函数。
该库rcom允许调用 COM 对象,因此理论上,对于任何公开为 COM 对象的 .NET 程序集来说,这应该是可能的。
为了简单起见,我将看看是否可以调用.Reverse()中的函数System.Text,该函数默认从 .NET 框架公开为 COM 对象。
这是我到目前为止所尝试过的:
我获得了系统中的 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---
Run Code Online (Sandbox Code Playgroud)此 R 代码加载公开为 COM 对象的 .NET .dll:
library('rcom')
x <- comCreateObject("System.Text.ASCIIEncoding")
Run Code Online (Sandbox Code Playgroud)它肯定找到了 COM 对象:
x attr(,"类") 1 "COMObject"
我的问题是 - 如何调用.Reverse()此 COM 对象中的函数?
更新
在 .NET 中,调用将是:
string x = "hello".Reverse();
Run Code Online (Sandbox Code Playgroud)
那么,在 R 中,调用会是?
更新
有关 R 调用 C# 的示例,请参阅幻灯片 61 中在 Windows 上的应用程序中嵌入 R 中的 R调用C#。
请注意,它ProgId来自ProjectName.ClassName.NET 类。
我刚刚根据《在 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")
Run Code Online (Sandbox Code Playgroud)
这是 R 中的输出:
> DoCallback: xxxNULL
Run Code Online (Sandbox Code Playgroud)
以下是 .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");
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
笔记
为了使其发挥作用,所有内容都必须始终为 32 位或始终为 64 位。我通过使用以下设置使其在 32 位模式下工作:
如果您使用 Visual Studio 2012 (VS2012),那么如果您在 .NET 项目设置中勾选“注册 COM 互操作”,它将在编译时自动运行C:\Windows\Microsoft.NET\Framework\v4.0.30319\regtlibv12.exe以将您的自定义 .NET 类注册为系统范围的 COM 组件。但是,如果您使用 Visual Studio 2010 (VS2010),它不会自动运行regtlibv12.exe,所有此设置将创建 .tlb 文件(您必须regtlibv12.exe自己手动运行)。
可以通过调用“regtlibv12.exe -u MyComDLL.tlb”取消注册 COM 组件。
如果您构建项目,并且 VS2012 抱怨它无法写入输出 .dll,这意味着 R 由于调用而锁定了它x <- comCreateObject("InteropSample.MyClass32")。要解锁 .dll 以便可以编译 VS2012,请关闭 R,编译 C#,然后重新启动 R。
附加信息
rcom。rcom。