Возможно, я сумасшедший, но я начинаю получать удовольствие от этой идеи, даже если это просто для обучения: я пытаюсь использовать COM из Java, вызывая функции Ole32.dll через ЮНА . Согласно спецификации 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, поэтому я хотел бы знать, имеет ли код смысл? Не могу заставить его работать, потому что я застрял в какой-то другой глупой ошибке, прежде чем этот код будет вызван.
Будет ли этот способ работы с COM слишком медленным или он действительно станет возможным способом сделать это из Java, особенно если добавить один динамический прокси Java вместе с IDispatch COM?
Я знаю о JACOB и других COM-библиотеках из Java, и я их использовал. Просто пробую что-то новое для, как я уже говорил, опыта обучения.