I may be crazy, but I'm starting to have fun with this idea, even if it's just for learning: I'm trying to use COM from Java by calling Ole32.dll functions through JNA . According to the COM specification, a COM pointer is just a pointer to a pointer that points to an array of function pointers. I thought that since JNA allows you to call pointer functions, I should be able to call COM methods if I can get VMT (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 some code to create the IUnkown interface specified by the 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 little new to JNA, so I would like to know if the code makes sense? Couln't make it work, but I was stuck in some other stupid mistake before this code gets called.
Would this way make COM too slow, or could it be a feasible way to do it with Java, especially if you are going to some Java Dynamic Proxies with COM IDispatch?
I know about JACOB and other Java COM libraries, and I used them. Just try something new, as I mentioned, learning experiences.