Perhaps I'm crazy, but I'm starting to have fun with this idea even if it is just for the learning experience: I'm trying to use COM from Java by calling the Ole32.dll functions via JNA. According to the COM spec a COM interface pointer 开发者_如何学编程is just a pointer to a pointer that points to an array of function pointers. I thought since JNA allows to call function pointers I should be able to call COM interface methods if I can get the VMT (the array of function pointers).
Here is my IUnknown interface:
@IId("00000000-0000-0000-C000-000000000046")
public interface IUnknown {
int QueryInterface(Guid riid, PointerByReference ppvObject);
int AddRef();
int Release();
}
And here is a bit of code to create an IUnkown interface, given a 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 });
}
};
}
I'm still a bit new to JNA, so I would like to know if the code makes sense? Couln't get it to work yet cause I'm stuck at a some other silly error before this code gets invoked.
Will this way of doing COM be too slow or could it actually become a feasible way of doing it from Java, especially if one throw in some Java Dynamic Proxies along with COM's IDispatch?
I know about JACOB and the other COM libraries from Java and I've used them. Just trying something new for, like I mentioned, the learning experience.
Given that native COM is all built on C (not C++), this will technically work if the native code is using either C or stdcall calling conventions. JNA gives you all the tools you need to futz with the native memory and set up the stack for a function call.
Ultimately, though, you'd want to wind up with something that can parse a typelib and generate the interfaces you'll actually need, which I believe is what JACOB and com4j do.
EDIT
JNA now provides fairly comprehensive COM support, including reading of type libraries and event callbacks.
精彩评论