Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果COM对象是从.NET程序集中公开的,是否可以从R中调用COM对象?_.net_R_Com - Fatal编程技术网

如果COM对象是从.NET程序集中公开的,是否可以从R中调用COM对象?

如果COM对象是从.NET程序集中公开的,是否可以从R中调用COM对象?,.net,r,com,.net,R,Com,我想知道是否可以通过COM调用从R调用.NET函数 库rcom允许调用COM对象,因此理论上,对于作为COM对象公开的任何.NET程序集,这都是可能的 为了简单起见,我将查看是否可以调用System.Text中的.Reverse()函数,该函数默认情况下作为.NET framework中的COM对象公开 这就是我迄今为止所尝试的: 我在我的系统中获得了ProgID的列表(请参阅)。以下是我的系统中相关程序ID的列表: ---start list of COM ProgID entries---

我想知道是否可以通过COM调用从R调用.NET函数

rcom
允许调用COM对象,因此理论上,对于作为COM对象公开的任何.NET程序集,这都是可能的

为了简单起见,我将查看是否可以调用
System.Text
中的
.Reverse()
函数,该函数默认情况下作为.NET framework中的COM对象公开

这就是我迄今为止所尝试的:

  • 我在我的系统中获得了ProgID的列表(请参阅)。以下是我的系统中相关程序ID的列表:

    ---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---
    
    那么,在R中,调用将是

    更新

    有关R调用C#的示例,请参见幻灯片61中的R调用C#

    请注意,
    ProgId
    是.NET类中的
    ProjectName.ClassName

    通常您使用:


    s根据的幻灯片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")
    
    下面是.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");
                }
            }
        }
    }
    
    注释

  • 为了使其正常工作,所有内容都必须始终为32位或64位。我使用以下设置使其在32位模式下工作:

    • C#程序集(设置为32位)
    • R的版本(我在32位模式下使用了R)
  • 如果您使用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我知道这个问题很老,我将报告我的经验,以帮助未来的.Net/R开发人员

    无论我怎么尝试,我都无法引用
    rcom\u srv.tlb

    无法添加对
    C:\Program Files\R\R-2.15.3\library\rcom\libs\i386\rcom\u 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" 
    
    #在某些PC上,只有将其设置为使用IE代理设置时,才会下载软件包:
    setInternet2(真实)
    #这是一次性电话。
    安装程序包(“rcom”)
    #这是一次性电话。
    installstatconnDCOM()
    #可恢复呼叫
    >库('rcom')
    加载所需包:rscproxy
    >dll=comCreateObject(“XYZ.dotNetProject_R”)
    >动态链接库
    属性(,“类”)
    [1] “共同对象”
    >series=comInvoke(dll,“GetdotNetProject2DArray”、“abc123”、“2000-01-01”、“2010-01-01”)
    >系列
    [,1]         [,2]                 
    [1,] "2000-01-01" "1236.1" 
    

    COM不支持泛型,所以我只返回了一个字符串数组。我发现R只支持基本/基本的.Net类型,例如string、datetime、int等。当我尝试返回对象数组时,它失败了,并且.Net调用将NULL返回给R。

    System.Text.asciencoding
    没有
    反向方法。你是说
    string.Reverse
    ?@D Stanley是的,想调用string.Reverse。我想知道如何列出COM对象公开的方法?Use
    String
    也没有
    Reverse
    方法-它是
    IEnumerable
    中的一个扩展方法,可以反转隐式字符数组。啊!因此,问题之一是识别system.string公开为的COM对象的名称。它不是-
    system。从COM的角度来看,string
    被标记为
    不可处理的。如果你想找到一个COM可见的.NET框架类,那么你自己构建一个简单的COM类会更好。我已经为此绞尽脑汁好几个小时了,但是我不能添加引用。我做了
    regtlibv12.exe rcom_srv.tlb
    ,但在VS中的COM引用中没有对它的引用。当我浏览到tlb时,引用它时会出现错误。您是如何引用rcom_srv.tlb的?您的.NET程序集很可能未设置为32位。如果设置为64位(“全部”),则无法引用32位COM组件。让我知道这是否解决了问题。如果没有,我会在一台新电脑上按照我自己的说明进行相应的调整。现在我想起来了,我可能已经开始尝试R v2.15,然后放弃,回到v2.14,让它开箱即用。我已经更新了上面的答案。
    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");
                }
            }
        }
    }
    
    public STATCONNECTORSRVLib.StatConnectorClass rdcom = null;
    //public RCOMServerLib.InternalConnectorClass rdcom = null; // Use 'rcom' for debugging
    
    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))
            {
    
            }
        }
    }
    
    # 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"