gpt4 book ai didi

c# - 通过 COM4J 从 .NET 方法返回接口(interface)数组

转载 作者:IT老高 更新时间:2023-10-28 21:02:56 26 4
gpt4 key购买 nike

如何通过 COM4J 从 C# 方法将对象数组(实现 COM 接口(interface))返回到 Java 方法?

生成数组的示例 C# 类:

using System;
using System.Runtime.InteropServices;

namespace Example
{

[ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAnimal
{
string Speak();
}

[ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IFarm
{
[return:MarshalAs(UnmanagedType.SafeArray,
SafeArraySubType=VarEnum.VT_UNKNOWN)]
IAnimal[] GetAnimals();
}

[ComVisible(true), ClassInterface(ClassInterfaceType.None)]
public class Farm : IFarm
{
public IAnimal[] GetAnimals()
{
return new IAnimal[] { new Cow(), new Pig() };
}
}

internal class Cow: IAnimal
{
public string Speak()
{
return "Moo";
}
}

internal class Pig: IAnimal
{
public string Speak()
{
return "Oink";
}
}
}

生成的 .tlb 中的接口(interface)声明如下所示:

[
odl,
uuid(1FB5E376-E78D-3A2E-BEF3-F3C798FCF44C),
version(1.0),
oleautomation,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Example.IFarm")
]
interface IFarm : IUnknown
{
HRESULT _stdcall GetAnimals([out, retval] SAFEARRAY(IUnknown*)* pRetVal);
};

Java 客户端代码:

import com4j.*;

public class Example {
public static void main(String[] args) {
IFarm farm = ClassFactory.createFarm();
Com4jObject[] animals = farm.getAnimals();

for (Com4jObject o: animals) {
IAnimal animal = o.queryInterface(IAnimal.class);

if (animal != null) {
animal.speak();
}
}
}
}

这可以编译,但我在运行时收到此异常:

Exception in thread "main" com4j.ComException: 
unexpected conversion type: 500 : .\invoke.cpp:470
at com4j.Wrapper.invoke(Wrapper.java:185)
at $Proxy5.getAnimals(Unknown Source)
at MainClass.main(MainClass.java:7)
Caused by: com4j.ComException: unexpected conversion type: 500 : .\invoke.cpp:470
at com4j.Native.invoke(Native Method)
at com4j.StandardComMethod.invoke(StandardComMethod.java:35)
at com4j.Wrapper$InvocationThunk.call(Wrapper.java:354)
at com4j.Task.invoke(Task.java:55)
at com4j.ComThread.run0(ComThread.java:157)
at com4j.ComThread.run(ComThread.java:137)

我尝试过的其他事情:

  • 编码为 SAFEARRAY(VARIANT)* 而不是 SAFEARRAY(IUnknown*)*
    (这会引发相同的异常。)
  • 移除 MarshalAs 属性(tlbimp 无法创建代理方法)

有没有办法编码数组以便 COM4J 可以将其转换为有效的 Java 数组?

另外有没有办法在 Java 中分配一个数组并允许 .NET 方法填充它? (我试过了,但是 .NET 方法接收到数组的副本,Java 代码永远不会看到插入到副本中的对象。也许有办法覆盖它?)


编辑:这可能是相关的:https://stackoverflow.com/a/6340144/12048 - VBScript 似乎可以实现类似的功能

最佳答案

您是否尝试过将接口(interface)声明为 InterfaceIsDual 和/或 InterfaceIsIDispatch?

[ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAnimal
{
...

大多数 COM 互操作库都需要调度接口(interface);但是,我不确定 COM4J。您也可以使用抽象的 COM 基类而不是接口(interface)来实现相同的目标,但如果上述更改无法让您启动并运行,我会感到惊讶。

关于c# - 通过 COM4J 从 .NET 方法返回接口(interface)数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12711177/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com