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

时间:2011-04-11 19:50:32

标签: java com jna

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

这是我的IUnknown界面:

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

这里有一些代码来创建一个IUnkown接口,给定一个CLSID:

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库,我已经使用过它们。正如我所提到的那样,尝试新的东西,学习经验。

1 个答案:

答案 0 :(得分:2)

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

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

修改

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