2009-08-20 9 views
7

Dans mon application Java SWT, j'héberge un contrôle ActiveX tiers. J'utilise OleClientSite pour le faire.Java SWT interop avec COM - mettre un flotteur [] dans un variant?

// Ah, this works. :-) 
OleAutomation comObject = new OleAutomation(...); 

Il y a 2 petites fonctions simples que je veux appeler depuis Java. Voici les définitions des fonctions COM:

[id(5)] 
void easyFoo([in] int blah); 

[id(20)] 
void problemFoo([in] VARIANT floatArray); 

Facile, n'est-ce pas? Voici mon code à faire semblant:

// Ah, this works. :-) 
OleAutomation comObject = new OleAutomation("Some3rdPartyControlHere"); 

// Call easyFoo(42). This works. :-) 
int easyFooId = 5; 
comObject.invoke(easyFooId, new Variant[] { new Variant(42) }); 

// Call problemFoo(new float[] { 4.2, 7.0 }). This doesn't work. :-(
int problemFooId = 20; 
comObject.invoke(problemFooId, [ACK! What goes here?]); 

Le problème est sur la dernière ligne: comment puis-je passer un tableau flottant à la 3ème partie objet COM? AIDE!

+0

Merci pour ces commentaires. Je viens d'ajouter un commentaire expliquant ce que j'ai trouvé (et ce que j'ai fait * pas * trouver) sur SAFEARRAY. – VonC

+0

Ajout d'une autre référence à un projet Java manipulant 'SAFEARRAY'. Peut être cela pourrait aider. – VonC

+0

@Judah: le problème avec '' VARIANT' 'est que peut être n'importe quoi. Pourtant, si SAFEARRAY c'est, avez-vous vérifié http://j-integra.intrinsyc.com/support/com/doc/types/index.html et http://j-integra.intrinsyc.com/support/kb /Article.aspx?id=30430? – VonC

Répondre

1

Vous devez passer un tableau flottant. En termes de COM, cela signifie que VARIANT avec vt est défini sur VT_R4 | VT_ARRAY. Un tableau de variantes peut ne pas fonctionner car le document ne dit pas qu'il peut accepter un tableau de variantes (VT_VARIANT | VT_ARRAY). En Java, vous devriez pouvoir utiliser float [] comme type de paramètre. Sinon, vous pouvez toujours call the Windows API to construct a safe array of desired type.

+0

Merci pour la réponse. J'ai vu le "lire et écrire dans un tableau sécurisé" dans l'article Java que vous liez à. J'ai adapté ce code pour travailler pour les flottants, et cela semble fonctionner. Je posterai les résultats sous peu. –

0

Je suppose qu'il n'y a pas de constructeur qui prend un flottant [] car VARIANT ne possède pas de membre de groupe flottant.

Je pense que ce que vous devez faire pour faire ce travail est d'emballer vos flotteurs dans un SAFEARRAY (ick, et je ne sais pas comment en créer un en Java). Alternativement, vous pouvez essayer de sérialiser votre tableau en bits bruts et utiliser le membre BYTE * de la structure VARIANT, et passer un int qui a le nombre d'octets de sorte que vous puissiez désérialiser avec précision de l'autre côté (et je supposons que tout est dans le même processus et le même fil, sinon cela devient plus difficile).

[id(20)] 
void problemFoo([in] VARIANT bytes /* VT_BYREF|VT_UI1 */, [in] VARIANT byteCount /* VT_UI4 */); 
+0

Même processus, même thread, mais il n'y a pas de problèmeFoo (octets, byteCount).L'objet COM est un contrôle tiers, un qui prend uniquement VARIANT et les états de la documentation que vous devez transmettre dans un tableau flottant. –

+0

D'accord. Eh bien, j'espère que cette réponse ou l'autre vous indiquera la bonne direction. Peut-être contacter le fournisseur et demander s'ils ont un exemple de code Java. –

+0

Le fournisseur ne prend plus en charge ce composant COM, donc je ne peux pas obtenir de support de leur part. (Nous essayons d'enlever ce contrôle de la 3ème partie, mais ces choses prennent du temps.) Je vais enquêter sur le membre byte *. Si cela fonctionne, je vais marquer le vôtre comme la bonne réponse. –

0

Qu'est-ce qui ne va pas avec la création d'un tableau de Variant et son remplissage avec vos valeurs de tableau flottant?

Variant[] problemFooArgs = new Variant[myFloats.length]; 
for(int i=0; i<myFloats.length; i++) 
{ 
     problemFooArgs[i] = new Variant(myFloats[i]); 
} 

Si elle a vraiment besoin qu'un seul argument (un tableau de float), vous pouvez essayer un niveau d'indirection:

Variant[] problemFooArgs = new Variant[1]; 
Variant[] myFooArgs = new Variant[1]; 
for(int i=0; i<myFloats.length; i++) 
{ 
     myFooArgs [i] = new Variant(myFloats[i]); 
} 
problemFooArgs[0] = myFooArgs; 

Si l'approche simple ne fonctionne pas et que vous ne besoin un SAFEARRAY, vous pouvez essayer et créer un après l'exemple "Reading and writing to a SAFEARRAY", en utilisant les constantes de org.eclipse.swt.internal.win32.OS. Mais il semble que pour char[] seulement.

Autre source d'inspiration pour la création de la SAFEARRAY pertinente:

class SafeArray of project com4j (et sa classe associée, comme Variant)

+0

Merci, il ne m'est pas venu à l'esprit que je pouvais envoyer un tableau de variantes. Je vais essayer cela et revenir à vous. –

+0

En ce qui concerne SAFEARRAY, je ne pense pas avoir besoin d'un SAFEARRAY, comme le COM IDL le spécifiera quand il en aura besoin, n'est-ce pas? J'ai vu des IDL de fonctions qui nécessitent SAFEARRAY; ce particulier IDL déclare que j'ai besoin d'un variant. Quoi qu'il en soit, je vais essayer et revenir à vous. –

+0

En fait, maintenant je ne suis pas si sûr; En fait, il peut être un SAFEARRAY. Hrmmm. –