4 votes

Puis-je utiliser COM à partir de Java via JNA ?

Je suis peut-être fou, mais je commence à m'amuser avec cette idée, même si c'est juste pour l'expérience d'apprentissage : J'essaie d'utiliser COM à partir de Java en appelant les fonctions de Ole32.dll par l'intermédiaire de JNA . Selon la spécification COM, un pointeur d'interface COM est juste un pointeur vers un pointeur qui pointe vers un tableau de pointeurs de fonctions. Je pensais que puisque JNA permet d'appeler des pointeurs de fonction, je devrais pouvoir appeler des méthodes d'interface COM si je peux obtenir le VMT (le tableau de pointeurs de fonction).

Voici mon interface IUnknown :

@IId("00000000-0000-0000-C000-000000000046")
public interface IUnknown {
    int QueryInterface(Guid riid, PointerByReference ppvObject);
    int AddRef();
    int Release();
}

Et voici un bout de code pour créer une interface IUnkown, étant donné un 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 });
        }
    };
}

Je suis encore un peu novice en matière de JNA, alors j'aimerais savoir si ce code a un sens ? Je n'ai pas encore réussi à le faire fonctionner parce que je suis bloqué à une autre erreur stupide avant que ce code ne soit invoqué.

Cette façon de faire de COM sera-t-elle trop lente ou pourrait-elle devenir une façon réalisable de le faire à partir de Java, surtout si l'on ajoute quelques mandataires dynamiques Java à IDispatch de COM ?

Je connais JACOB et les autres bibliothèques COM de Java et je les ai utilisées. J'essaie juste quelque chose de nouveau pour, comme je l'ai mentionné, l'expérience d'apprentissage.

2voto

technomage Points 3774

Étant donné que le COM natif est entièrement construit en C (et non en C++), cela fonctionnera techniquement si le code natif utilise les conventions d'appel C ou stdcall. JNA vous fournit tous les outils nécessaires pour manipuler la mémoire native et configurer la pile pour un appel de fonction.

En fin de compte, cependant, vous voudriez vous retrouver avec quelque chose qui peut analyser une typelib et générer les interfaces dont vous aurez réellement besoin, ce que JACOB et com4j font, je crois.

EDITAR

JNA offre désormais un support COM assez complet, y compris la lecture des bibliothèques de types et les rappels d'événements.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X