问题标签 [safearray]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
7295 浏览

winapi - 如何通过 IDispatch 将 SAFEARRAY 传递给 COM 对象?

我正在尝试调用 COM 对象的方法,其中记录的参数之一是“字节数组”。实际声明取决于您正在查看的每种语言的文档:

  • C#语言中:

    /li>
  • C++语言;

    /li>
  • VB语言

    /li>
  • F#语言中:

    /li>

我正在使用的对象也可以使用COM访问。该对象提供了一个早期绑定接口 ,ICryptoTransform该接口将方法声明为 using SAFEARRAY

类型库

  • 使用IDL语法

    /li>
  • 使用对象 Pascal语法:

    /li>

这意味着在使用早期绑定时,您必须传递方法 a SAFEARRAY。我使用的语言支持 SafeArray API,我是否可以轻松地执行调用:

这是类似 java 语言的相同代码:

一切正常;但这不是我的问题。

注意:我试图强调这是一个与语言无关的问题,因为COM 是一种与语言无关的技术。但是在某些时候,我们必须实际使用一种语言来演示代码。有些人将语言与技术混淆了。如果我知道 Knuth 发明的语言,我会使用它。

但是后期绑定IDispatch呢?

现在我们知道我们可以将 a 传递SAFEARRAY给 COM 对象(使用early-binding时),我需要解决使用late-binding传递数组的问题。

注意:除此之外,如何通过 IDispatch 将 SAFEARRAY 传递给 COM 对象的问题对我很有用ICryptoTransform

IDispatch一些语言提供了在运行时通过接口调用方法的自动机制(即后期绑定)。事实上IDispatch,后期绑定是为 VBScript 发明的:

.NET 4.0 中添加了后期绑定编译器自动魔法:

Delphi 中也存在后期绑定编译器魔法:

碰巧在使用 Dephi,这个调用失败了。

但这并不是真正的编译器魔法

VBScript、C# dynamic 和 Delphi 所做的并不是什么神奇的事情。他们只是在打电话IDispatch.Invoke

混乱正在设置这些参数:

真正的技巧是dispParams包含参数的结构。

参数将是一个变体

通过 DISPARAMS 传递的参数都是变体:

所以无论发生什么,我的“字节数组”都将是一个变体。

A VARIANT,在 Win32 中,只是一个联合,它包含:

  • VARTYPE vt:联合中的数据类型。
  • 适当的工会成员,例如:

    /li>

到目前为止,我一直在传递一种类型的变体:

MSDN 记录了当您想使用parray union时必须执行的操作VT_ARRAY | *

价值VT_ARRAY | <anything>

说明:传递了一个数据类型的数组。VT_EMPTY 和 VT_NULL 是与 VT_ARRAY 组合的无效类型。pbyrefVal中的指针指向一个数组描述符,它描述了数组的维度、大小和内存中的位置。

这意味着使用该parray成员:

您需要将parraymember 设置为指向SAFEARRAY结构的指针:

就我而言,我的字节数组实际上是 a SAFEARRAY,然后将其存储在一个变体中:

注意:当然我还没有疯狂到自己创建了这个安全数组;我正在使用SafeArrayCreateapi 功能。我只是在证明这一切都是可知的,而不是魔法。

换句话说,我传递了一个字节的数组变体

换句话说,我正在传递一个字节数组,包装在一个变体中,因为所有调用:

一定是。除了后期绑定调用抛出错误:

那么我可能做错了什么?

如何将一个字节数组传递给后期绑定 IDispatch调用?

我的问题

如何通过 IDispatch 将 SAFEARRAY 传递给 COM 对象?

0 投票
2 回答
2271 浏览

delphi - delphi7中使用PSafeArray调用COM时出错

我有一个需要使用 COM 调用的过程,它在 C# 中声明如下:

导入的 TypeLibrary 中的 Delphi 声明为:

我有这段代码可以将整数数组转换为 PSafeArray:

这段代码调用我的 COM 函数

但错误发生:

“ EOLeExeption 带有消息 'SafeArray of rank 0 已被传递给期望 rank 1 数组的方法' ...”

我应该怎么做?

0 投票
2 回答
2388 浏览

c# - 将 IUnknowns 的 SAFEARRAY 转换/转换为接口指针的可迭代数组

我在 C# 中有以下接口,其中一个具有相同名称(没有我)的类实现它。

公共类 Order 的实现: IOrder 只是三个私有字段和一个带有所需 3 个参数的构造函数。

在其他地方,我有以下方法,其结果是我想在 C++ 非托管代码中工作,通过 COM 和 .tlb/.tlh 文件传输到那里。

我已经设法使用 C# 托管代码在 C++ 非托管代码之间进行基础工作。

但是类数组被证明是一个不同的挑战......

我承认,对我来说,COM 是新的,令人困惑,C++ 早已被遗忘......,但我正在开发这两个库,所以我不会放弃;我希望 C++ DLL 在某些程序和我的 C# 代码之间充当代理。

澄清:我既没有使用 MFC 也没有使用 ATL。我在 C++ 代码中使用#import 来获取 C# 生成的接口和类指针以及其他我不太了解的 COM 内容。

经过一个小时的研究,我只是去这里寻求帮助>.<

以下是我想要实现的 C++ 代码。

现在,我需要一些我还不明白的 COM 魔法来将 SAFEARRAY* 转换为 IOrderPtr* 或其他东西,这样我就可以遍历返回的整个数组并调用“Order”类型的方法

  • 获取数量()
  • 获取订单类型()
  • 获取位置类型()

因此,对于第一个周期,我将获得值 1、2、3,对于第二个周期,我将获得值 4、5、6。

因为我是 C++ 和 C# 库的作者,所以我可以跳过所有这些 COM 疯狂的东西,并制作方法来获取集合计数和其他方法来获取特定索引上的属性值。

但这似乎并不好。我怀疑我想要的机制很简单,但我在谷歌上找到的所有答案总是缺少一些东西。

0 投票
1 回答
691 浏览

c# - 尝试获取类方法指针时的 E_NOINTERFACE

我正在从 C++ 非托管代码中调用 C# 方法。我从数组中返回的类实例中获取值时遇到问题。

我已经稍微简化了代码

这是有问题的方法。

这是 IScOrder 接口

这是 ScOrder 的实现

这是 C++ 代码,在我之前的请求中得到 Zdeslav Vojkovic 的帮助后。问题在评论中描述

  • 我没有使用 ATL 或 MFC。
  • C++ tlb 文件是通过 regasm 生成的。

COM 初始化和调用 GetOrders 方法效果很好

感谢 Zdeslav,我发现我可以在 order(punk) 中进行调试:

所以我走进秩序(朋克)看看那里发生了什么。我进入了一个“comip.h”

...然后我进入了 _QueryInterface(p) 实现,也在 comip.h

现在这里的问题是返回的“hr”的值是 E_NOINTERFACE ...这是不对的。

我不是 C++ 或 COM 专家...请帮助 :)

0 投票
1 回答
637 浏览

.net - 是否可以在 SAFEARRAY 中编组 ref 参数

这是我的 C# 服务器方法:

我的 C++ 客户端正在设置并调用此方法。这工作正常,但状态和输出变量似乎没有链接。就好像它们是按值而不是按引用传递的。

这是我的客户代码:

有人可以在设置 SAFEARRAY 参数方面提供帮助,以便将“ref”参数复制回来吗?

0 投票
2 回答
23341 浏览

c++ - 如何遍历 SAFEARRAY **

如何遍历 C++ 安全数组指针指向指针并访问其元素。

我试图复制 Lim Bio Liong http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/022dba14-9abf-4872-9f43-f4fc05bd2602发布的解决方案, 但最奇怪的是 IDL方法签名出来是

代替

有任何想法吗?

提前致谢

0 投票
2 回答
4767 浏览

c# - 通过 COM Interop 编组托管结构的 SAFEARRAY

我正在尝试将从 ac# 库导出的结构数组传递给 c++ 代码。目标是将结构的 SAFEARRAY 从 c++ 传递到 c#。

我已按照指示

http://limbioliong.wordpress.com/2011/07/16/marshaling-a-safearray-of-managed-structures-by-com-interop-part-2/

但是通过调用 GetRecordInfoFromTypeInfo 得到这个错误

0x80028019 旧格式或无效类型库。

0 投票
3 回答
1045 浏览

c++ - 如何将 fstream 读入 LPSAFEARRAY?

我正在尝试在 C++ 中调用托管 dll 上的方法。其中一个参数是字节数组,库导入将其转换为 LPSAFEARRAY。字节数组/LPSAFEARRAY 旨在成为文件的内容。如何将文件读入 LPSAFEARRAY 以传递给方法?

这是生成的库头文件中的函数签名:

第二个参数是另一个字节数组,当它从方法返回时我需要使用它。

0 投票
1 回答
1830 浏览

c# - 如何从多维 PSafeArray 中获取数据?

我需要从PSafeArrayDelphi 中读取数据。
PSafeArray是由用 C# 开发的 DLL 中实现的方法返回的。此方法返回一个二维字符串数组string[,]。如何PSafeArray在 Delphi 中读取这样的结果?

0 投票
0 回答
468 浏览

vb.net - 返回 SAFEARRAY(Long) 导致 SafeArrayTypeMismatchException 的 COM 对象

我使用他们提供的 API 类型库为我们在工作中使用的程序编写插件。它是一个名为 SCAPI 的 COM 对象。COM 对象是为 VB6 编写的,因此当我为 .NET 添加它的引用时,会创建它的互操作版本。

当我使用以下代码时,它应该根据文档返回一个 SAFEARRAY(Long),我收到一条错误消息,说我有一个 SafeArrayTypeMismatchException。

该错误是从 SCAPI.PropertyBagClass.get_Value(Object Property) 函数引发的,该函数是 COM 对象的一部分,而不是我写的东西。经过我所做的所有研究,我似乎无法弄清楚我需要做什么才能使其正常工作。我使用 tlbimp.exe 来获取方法信息,但它似乎不包含任何 [out] 标签,即使我使用了相同的函数 oBag.Value("Name"),它返回一个字符串值并且不会抛出错误: