【发布时间】:2011-08-03 08:37:09
【问题描述】:
也许我疯了,但我开始对这个想法感到有趣,即使它只是为了学习经验:我正在尝试通过 JNA 调用 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 还是有点陌生,所以我想知道代码是否有意义?无法让它工作,因为在调用此代码之前我遇到了其他一些愚蠢的错误。
这种执行 COM 的方式会不会太慢,或者它实际上是否可以成为从 Java 执行它的一种可行方式,尤其是如果将一些 Java 动态代理与 COM 的 IDispatch 一起投入使用?
我知道 JACOB 和其他来自 Java 的 COM 库,并且我已经使用过它们。就像我提到的,只是为了学习体验尝试一些新的东西。
【问题讨论】:
-
我刚刚能够调用 IUnknown.QueryInterface :-)。它似乎工作
-
这看起来很棒,你能发布整个代码吗?
-
谢谢。我之前找到了您的代码,并尝试以这种方式使用 TaskBar API。它的效果 - 令我惊讶 - 非常好。
-
太棒了 :-) 那么我的时间花得很好......