【问题标题】:Java SWT interop with COM - putting a float[] into a Variant?Java SWT 与 COM 互操作 - 将 float[] 放入 Variant?
【发布时间】:2009-08-20 04:09:02
【问题描述】:

在我的 Java SWT 应用程序中,我托管了一个第 3 方 ActiveX 控件。我正在使用 OleClientSite 来执行此操作。

// Ah, this works. :-)
OleAutomation comObject = new OleAutomation(...);

我想从 Java 调用 2 个简单的小函数。以下是 COM 函数定义:

[id(5)]
void easyFoo([in] int blah);

[id(20)]
void problemFoo([in] VARIANT floatArray);

很简单,对吧?这是我的伪装代码:

// Ah, this works. :-)
OleAutomation comObject = new OleAutomation("Some3rdPartyControlHere");

// Call easyFoo(42). This works. :-)
int easyFooId = 5;
comObject.invoke(easyFooId, new Variant[] { new Variant(42) });

// Call problemFoo(new float[] { 4.2, 7.0 }). This doesn't work. :-(
int problemFooId = 20;
comObject.invoke(problemFooId, [ACK! What goes here?]);

问题出在最后一行:如何将浮点数组传递给第 3 方 COM 对象?帮助!

【问题讨论】:

标签: java activex swt com-interop ole


【解决方案1】:

您需要传递一个浮点数组。在 COM 术语中,这意味着 s 是一个 VARIANT,其中 vt 设置为 VT_R4|VT_ARRAY。变体数组可能不起作用,因为文档没有说它可以接受变体数组 (VT_VARIANT |VT_ARRAY)。在 java 中,您应该能够使用 float[] 作为参数类型。如果没有,您可以随时call the Windows API to construct a safe array of desired type

【讨论】:

  • 感谢您的回答。我在您链接到的 Java 文章中看到了“读取和写入安全数组”。我已经修改了该代码以适用于浮点数,并且它似乎可以工作。我会尽快发布结果。
【解决方案2】:

我怀疑没有采用 float[] 的构造函数,因为 VARIANTs 没有 float 数组成员。

我认为你需要做的就是把你的浮点数打包成一个SAFEARRAY(我不知道如何在 Java 中创建一个)。

或者,您可以尝试将数组序列化为原始位并使用 VARIANT 结构的 BYTE* 成员,并传递一个包含字节数的 int 以便您可以在另一端准确地反序列化(我假设这都是在同一个进程和线程中,否则会变得更难)。

[id(20)]
void problemFoo([in] VARIANT bytes /* VT_BYREF|VT_UI1 */, [in] VARIANT byteCount /* VT_UI4 */);

【讨论】:

  • 同一个进程,同一个线程,但是没有问题Foo(bytes, byteCount)。 COM 对象是第 3 方控件,它只接受 VARIANT,文档说明您应该传入一个浮点数组。
  • 好的。好吧,希望这个或其他答案为您指明正确的方向。也许联系供应商并询问他们是否有一些 Java 示例代码。
  • 供应商不再支持这个 COM 组件,所以我无法从他们那里获得支持。 (我们正试图摆脱这个第 3 方控制,但这些事情需要时间。)我将调查 byte* 成员。如果可行,我会将您的答案标记为正确答案。
  • 好吧,另一边的控件将期待一些特定的类型。它应该拒绝任何未在 VARIANT 的 vt 字段中指定该类型的内容。最简单的做法是附加一个调试器(VS 或 NTSD)并逐步执行函数调用的反汇编。控件在哪里进行比较应该非常明显,您可以立即知道它是否需要 SAFEARRAY 或什么。
  • 杰夫,您可以指出我的任何资源,确切地解释如何做到这一点?我非常精通 Java 和 .NET 的调试器,但在调试本机代码时却傻眼了。
【解决方案3】:

创建一个 Variant 数组并用浮点数组值填充它有什么问题?

Variant[] problemFooArgs = new Variant[myFloats.length]; 
for( int i=0; i<myFloats.length; i++)
{
        problemFooArgs[i] = new Variant(myFloats[i]);
}

如果它真的只需要一个参数(浮点数组),你可以尝试一级间接:

Variant[] problemFooArgs = new Variant[1]; 
Variant[] myFooArgs = new Variant[1]; 
for( int i=0; i<myFloats.length; i++)
{
        myFooArgs [i] = new Variant(myFloats[i]);
}
problemFooArgs[0] = myFooArgs;

如果简单的方法不起作用并且您确实需要 SAFEARRAY,您可以尝试使用 org.eclipse.swt.internal.win32.OS 的常量在示例“Reading and writing to a SAFEARRAY”之后创建一个。但它似乎只适用于char[]

创建相关 SAFEARRAY 的其他灵感来源:

class SafeArray of project com4j(及其关联类,如Variant

【讨论】:

  • 谢谢,我没有想到我可以发送一系列变体。我会尝试并回复你。
  • 关于 SAFEARRAY,我认为我不需要 SAFEARRAY,因为 COM IDL 会指定何时需要,对吧?我见过需要 SAFEARRAY 的函数的 IDL;这个特定的 IDL 声明我需要一个变体。不管怎样,我会试试这些,然后回复你。
  • 其实,现在我不太确定;它实际上可能是一个 SAFEARRAY。嗯。
  • 传入变体数组似乎不起作用。在实际代码中,problemFoo 需要 2 个参数,都是浮点数组。
  • 我会尝试做一个 SAFEARRAY 并回复你。
猜你喜欢
  • 2012-06-18
  • 2014-09-03
  • 2011-07-02
  • 2010-11-12
  • 2012-02-27
  • 2012-03-31
  • 2011-04-11
  • 2010-12-14
  • 1970-01-01
相关资源
最近更新 更多