也许我很疯狂,但即使只是为了学习经验,我也开始玩这个想法了:我试图通过{{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库,我已经使用过它们。正如我所提到的那样,尝试新的东西,学习经验。
答案 0 :(得分:2)
鉴于本机COM都是基于C(而不是C ++)构建的,如果本机代码使用C或stdcall调用约定,这在技术上将起作用。 JNA为您提供了使用本机内存所需的所有工具,并为函数调用设置了堆栈。
但是,最终,您最终想要解析一个类型库并生成您实际需要的接口,我相信这是JACOB和com4j所做的。
修改强>
JNA现在提供相当全面的COM支持,包括读取类型库和事件回调。