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

问题描述:

也许我很疯狂,但即使只是为了学习体验,我也开始享受这个想法:我试图通过调用Ole32.dll函数通过JNA来从Java使用COM。根据COM规范,COM接口指针只是指向指向函数指针数组的指针的指针。我想,因为JNA允许调用函数指针,所以我应该可以调用COM接口方法,如果我可以得到VMT(函数指针数组)。我可以通过JNA从Java使用COM吗?

这里是我的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 ,所以我想知道代码是否有意义? Couln't得到它的工作,因为我被困在这个代码被调用之前的一些其他愚蠢的错误。

这种做COM的方式是否会太慢,或者实际上它可能成为从Java实现它的一种可行的方式,尤其是如果在COM的IDispatch中引入一些Java Dynamic Proxies?

我知道JACOB和来自Java的其他COM库,我已经使用过它们。只是尝试一些新的东西,比如我所提到的学习体验。

+0

我刚刚能够调用IUnknown.QueryInterface :-)。它似乎工作 – 2011-04-12 13:29:15

+0

这看起来不错,你可以发布整个代码? – Rekin 2013-08-22 15:15:31

+0

更多代码在这里:http://blog.abstractinvoke.com/2011/07/using-com-from-java-via-jna/ – 2013-08-27 20:06:53

鉴于本机COM全部构建在C(而不是C++)上,如果本机代码使用C或stdcall调用约定,这在技术上将起作用。 JNA为您提供了所需的所有工具,以便与本机内存保持一致,并为函数调用设置堆栈。尽管如此,最终你会想到能够解析typelib并生成实际需要的接口的东西,我相信这是JACOB和com4j所做的。

编辑

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