vb.net - 编码返回 Double() 以在 VBA 中使用的 .Net 函数

标签 vb.net marshalling com-interop

这是我在 .Net 中的函数:

<Runtime.InteropServices.ComVisibleAttribute(True)>
Public Function Unhex(hex As String) As Double()
    Dim GetArr As Double() = HexStringToDoubleArray(hex)
    Return GetArr
End Function

下面是我想在 VBA 中使用它的方式:

Dim ret() As Double
ret = LinkToComLib.Unhex("EDC531...")

有数百个示例说明如何将数组传递到 .Net (eg) , 但我发现唯一显示相反的是 this MS page ,并且它没有显示它在 VBA(甚至 COM)端使用。也许我使用了错误的搜索词。无论如何:

  1. 我可以使用 MarshalAs 从 .Net 导出 Double() 吗,或者我是否需要使用 Marshal.Copy 或类似的(正如我怀疑的那样,因为它是受管理的)?
  2. 如果我必须Copy,那么 IntPtr 是正确的返回类型吗?
  3. 我是否认为 Dim ret() As Double 是一个指向 malloc 数组或 SAFEARRAY 的指针?在这种情况下,这是在 VBA 中使用的正确类型吗?
  4. 在 VBA 中创建具有适当大小(总是 492!)的数组,然后将其传递给函数是否有任何帮助?也许释放?

如果有人有指向此示例的指针 - 一个 double (或整型)数组连同相应的 VBA 代码一起从 .Net 中传递出去,我很可能可以从那里获取它。但是,如果有人对上述问题有答案,他们喜欢 VB.Net 或 C#,我将不胜感激。

最佳答案

您需要用 <MarshalAs(UnmanagedType.SafeArray)> 修饰返回值属性。

VB.Net 示例:

Imports System.Runtime.InteropServices

<ComClass(ArrayExample.ClassId, ArrayExample.InterfaceId)> _
Public Class ArrayExample
    ' These  GUIDs provide the COM identity for this class  and its COM interfaces.
    Public Const ClassId As String = "e510d899-dad1-412b-94ea-6c726fe9f9da"
    Public Const InterfaceId As String = "ef3498f0-22b4-4c2a-aeb1-22936c9757eb"

    Public Function Unhex(hex As String) As <MarshalAs(UnmanagedType.SafeArray)> Double()
        Dim GetArr As Double() = {2.0R, 5.0R}
        Return GetArr
    End Function
End Class

VBA 用法:

Sub t()
   Dim c As ExampleComArrayReturn.ArrayExample
   Set c = New ExampleComArrayReturn.ArrayExample
   Dim arr() As Double
   arr = c.Unhex("AABB")
End Sub

编辑:忘记提及这使用了 ComClassAttribute Class让编译器为您的类生成接口(interface)。


编辑 2 以回应后续问题。

要调试您的 COM 库项目,请转到项目属性的“调试”选项卡。选择“启动外部程序”并将其设置为运行 Excel。您还可以在“命令行参数”中指定要打开的工作簿。现在,当您单击“开始”按钮时,将启动 Excel 并触发代码中的断点。

Setup Run External Application


编辑 3:

要解决面向 .Net 3.5 的问题,您可以使用稍微不太方便的方法将调试器附加到 Excel 进程。如果您使用的是 VS2008,则上述方法将起作用。新的 VS 版本将需要附加到进程。可能有一种方法可以在 vproj.user 文件中指定此信息,但我还没有找到允许使用特定框架版本直接启动的魔法属性类型。

根据您的 VS 版本,“附加到进程”项将位于工具 (VS2013) 或调试 (VS2017) 菜单下,或者您可以使用快捷键 cntrl-alt-p。

显然启动 Excel 并加载您的工作簿。然后在 VS 中启动 Attach to Process 对话框。单击“选择”按钮,然后单击“调试这些类型”单选按钮。选择“托管(v3.5、v3.0、v2.0)代码”类型并单击“确定”按钮。然后选择Excel进程,点击“附加”。

enter image description here

关于vb.net - 编码返回 Double() 以在 VBA 中使用的 .Net 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48773718/

相关文章:

vb.net - 关闭每种方法的Visual Studio/VB.Net行

mysql - 在vb.net数据 GridView 中选择多个表sql - sql &vb.net

.net - 发布 Tlb 新版本以及何时需要重新引用 Tlb

java - Eclipse RCP - 程序中的 JAXB 异常,但在最小示例中不存在 : javax. xml.bind.JAXBElement 或其任何父类(super class)在此上下文中已知

C# COM 互操作 : Writing to a Cell in an Excel Sheet

vba - 在 Excel VBA 中调用没有管理权限的 COM 互操作 regasm

mysql - mysql select 查询的循环

javascript - 将 GridView 列值传递给 Javascript 函数 - OnClientClick

interface - SAP .NET 连接器 : System exception thrown while marshaling . NET 类型

c# - C# 和非托管 C 库之间的互操作