开发者

Can I use COM from Java via JNA?

开发者 https://www.devze.com 2023-02-23 13:11 出处:网络
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

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

精彩评论

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