开发者

Can I use COM from Java via JNA?

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜