我可以通过JNA从Java使用COM吗?

也许我很疯狂,但即使只是为了学习经验,我也开始玩这个想法:我试图通过
JNA调用Ole32.dll函数来使用Java中的COM.根据COM spec一个COM接口指针只是一个指向指向函数指针数组的指针的指针.我认为既然JNA允许调用函数指针,我应该能够调用COM接口方法,如果我能得到VMT(函数指针数组).

这是我的IUnknown界面:

@IId("00000000-0000-0000-C000-000000000046")
public interface IUnknown {
    int QueryInterface(Guid riid, PointerByReference ppvObject);
    int AddRef();
    int Release();
}

在给定CLSID的情况下,这里有一些代码来创建IUnkown接口:

public static IUnknown createInstance(Guid clsId) {
    IId iidA = IUnknown.class.getAnnotation(IId.class);
    if (iidA == null)
        throw new IllegalArgumentException("Interface needs to be annotated with an IId");
    Guid iId = new Guid(iidA.value());
    Ole32 ole32 = WindowsJna.OLE32.get();
    PointerByReference p = new PointerByReference();
    int res = ole32.CoCreateInstance(clsId, null, Ole32.CLSCTX_INPROC, iId, p);
    if (res != Ole32.S_OK)
        throw new WinApiException(res);
    final Pointer interfacePointer = p.getValue();
    final Pointer vTablePointer = interfacePointer.getPointer(0);
    final Pointer[] vTable = new Pointer[3];
    vTablePointer.read(0, vTable, 0, 3);
    return new IUnknown() {
        public int QueryInterface(Guid riid, PointerByReference ppvObject) {
            Function f = Function.getFunction(vTable[0], Function.ALT_CONVENTION);
            return f.invokeInt(new Object[] { interfacePointer, riid, ppvObject });
        }
        public int AddRef() {
            Function f = Function.getFunction(vTable[1], Function.ALT_CONVENTION);
            return f.invokeInt(new Object[] { interfacePointer });
        }
        public int Release() {
            Function f = Function.getFunction(vTable[2], Function.ALT_CONVENTION);
            return f.invokeInt(new Object[] { interfacePointer });
        }
    };
}

我对JNA还是有点新手,所以我想知道代码是否有意义? Coul不能让它工作,因为在调用此代码之前我遇到了其他一些愚蠢的错误.

这种做COM的方式是否太慢,或者它实际上是否可以成为一种可行的方式来实现它,特别是如果一个Java动态代理与COM的IDispatch一起抛出?

我知道JACOB和Java中的其他COM库,我已经使用过它们.就像我提到的那样,尝试新的东西,学习经验.

最佳答案 鉴于本机COM都是基于C(而不是C)构建的,如果本机代码使用C或stdcall调用约定,这将在技术上有效. JNA为您提供了使用本机内存进行futz所需的所有工具,并为函数调用设置了堆栈.

但最终,您最终想要解析一个类型库并生成您实际需要的接口,我相信这就是JACOB和com4j所做的事情.

编辑

JNA现在提供相当全面的COM支持,包括读取类型库和事件回调.

点赞