【问题标题】:How can I pass VBA variant array data type through COM interop into C# method如何通过 COM 互操作将 VBA 变体数组数据类型传递给 C# 方法
【发布时间】:2020-07-01 16:03:32
【问题描述】:

目前我正在尝试通过 COM 互操作将变体数据类型数组传递给 c# 方法。问题是,将其传递为:

[MarshalAs(UnmanagedType.SafeArray)

但这似乎不起作用,有没有人有关于如何将它作为参数传递的任何提示?

这是我完整的 c# 源代码:

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Reflection;

namespace ExpandExcel
{
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    public class ExpandExcelStandard
    {
        #region Public Static Methods

        [return: MarshalAs(UnmanagedType.SafeArray)]
        public static T[] RemoveDuplicates<T>([MarshalAs(UnmanagedType.SafeArray)] ref T[] arr)
        {
            // Creates a hash set based on arr
            HashSet<T> set = new HashSet<T>(arr);
            T[] resultArr = new T[set.Count];
            set.CopyTo(resultArr);
            return resultArr; // Return the resultArr
        }

        #endregion
    }
}

这是我的完整 VBA 源代码:

Sub main()
    Dim arr(1000000) As Variant

    Dim ExpandExcel As ExpandExcelStandard
    Set ExpandExcel = New ExpandExcelStandard

    For i = 0 To UBound(arr)
        Randomize
        arr(i) = Int((1000000 + 1) * Rnd)
    Next i

    Dim resultArr() As Variant

    resultArr = ExpandExcel.RemoveDuplicates(arr)
End Sub

【问题讨论】:

  • 您需要向我们展示完整的 C# 声明和完整的原生定义(vba、其他)
  • 我的意思不是这是一个一般性问题,我想说的是,将其编组为安全数组是行不通的。我希望人们就他们认为如何解决这个问题给我一些建议。
  • 很有可能您甚至不需要特定的 MarshalAs。 p/invoke 提供了很多可能性,它实际上取决于互操作边界的两侧。如果您需要帮助,请提供代码
  • 我已经编辑了原始问题以包含源代码:)
  • 确实真正的问题是你可以调用这个方法。通用方法和静态方法都不是 [ComVisible]。要匹配 VBA 代码,它必须是 public object[] RemoveDuplicates(ref object[] arr)。顺便说一句,您将如何定义这些对象的相等性是一个谜。

标签: c# .net vba com com-interop


【解决方案1】:

你不能在 COM 中使用泛型,你不能使用静态函数等等。 这是一个应该可以工作的类似代码:

VB

Sub main()
    Dim arr(1000000) As Variant

    For i = 0 To UBound(arr)
        Randomize
        arr(i) = Int((1000000 + 1) * Rnd)
    Next i

    Set ExpandExcel = CreateObject("ExpandExcelStandard") // I used late binding but early is fine too
    resultArr = ExpandExcel.RemoveDuplicates(arr)
End Sub

C#

[ProgId("ExpandExcelStandard")] // because I wanted late binding, I declared a progid
[ComVisible(true)]
public class ExpandExcelStandard
{
    // .NET object (w/o any Marshal spec) is passed as an automation Variant
    public object[] RemoveDuplicates(object[] arr) => new HashSet<object>(arr).ToArray();
}

【讨论】:

  • 没用,报错“找不到方法或数据成员”。
  • @user3551497 - 你确定你已经 100% 准确地复制了我的代码吗?我已经测试过了。
  • 在 object[] 之前添加 ref 对我有用,非常感谢您的帮助!
猜你喜欢
  • 2016-10-07
  • 2012-05-15
  • 2019-02-12
  • 2021-03-31
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
  • 2014-10-11
  • 1970-01-01
相关资源
最近更新 更多