2009-08-20 5 views
7

В моем приложении Java SWT у меня есть сторонний элемент управления ActiveX. Я использую OleClientSite для этого.Java SWT взаимодействует с COM - помещает float [] в вариант?

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

Есть две простые функции, которые я хочу вызвать с Java. Ниже приведены определения функций COM:

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

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

Простенько, правильно? Вот мой Притворитесь код:

// 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?]); 

Проблема заключается в последней строке: Как передать массив с плавающей точкой на 3-й объект сторона COM? ПОМОЩЬ!

+0

Благодарим вас за эти отзывы. Я просто добавил комментарий, объясняющий, что я нашел (и что я сделал * не * нашел) о SAFEARRAY. – VonC

+0

Просто добавила еще одну ссылку на проект Java, управляющий 'SAFEARRAY'. Может быть, это может помочь. – VonC

+0

@Judah: проблема с '' VARIANT'' это то, что потенциально может быть чем угодно. Тем не менее, если SAFEARRAY это, вы просмотрели http://j-integra.intrinsyc.com/support/com/doc/types/index.html и http://j-integra.intrinsyc.com/support/kb /Article.aspx?id=30430? – VonC

ответ

1

Вам необходимо пройти буев. В терминах COM это означает s a VARIANT с vt, установленным на VT_R4 | VT_ARRAY. Массив вариантов может не работать, поскольку в документе не говорится, что он может принимать массив вариантов (VT_VARIANT | VT_ARRAY). В java вы должны использовать float [] в качестве типа параметра. Если нет, вы можете всегда call the Windows API to construct a safe array of desired type.

+0

Спасибо за ответ. Я видел «чтение и запись в безопасный массив» в статье Java, на которую вы ссылаетесь. Я адаптировал этот код для работы с плавающей точкой и, похоже, работает. Я опубликую результаты в ближайшее время. –

0

Я подозреваю, что нет конструктора, который принимает float [], потому что VARIANT s не имеет члена массива float.

Я думаю, что вам нужно сделать, чтобы эта работа упаковывала ваши поплавки в SAFEARRAY (ick; и я понятия не имею, как создать ее на Java).

В качестве альтернативы вы можете попробовать сериализовать свой массив на необработанные биты и использовать член BYTE * из структуры VARIANT и передать int, у которого есть количество байтов, чтобы вы могли точно де-сериализовать с другой стороны (и я предположим, что это все в одном процессе и потоке, иначе это становится сложнее).

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

Тот же процесс, тот же поток, но нет проблемFoo (bytes, byteCount).COM-объект является сторонним элементом управления, который принимает только VARIANT, и в документации указано, что вы должны передать массив с плавающей точкой. –

+0

Хорошо. Хорошо, надеюсь, этот или другой ответ указывает вам в правильном направлении. Возможно, обратитесь к поставщику и спросите, есть ли у них пример кода Java. –

+0

Vendor больше не поддерживает этот компонент COM, поэтому я не могу получить от них поддержку. (Мы пытаемся отойти от этого стороннего элемента управления, но все это требует времени.) Я буду исследовать член байта *. Если это сработает, я помету ваш как правильный ответ. –

0

Что не так с созданием массива Variant и заполнением его значениями массива float?

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

Если это действительно нужно только один аргумент (массив с плавающей точкой), вы можете попробовать один уровень косвенности:

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; 

Если простой подход не работает, и вы нуждаетесь SAFEARRAY, вы можете попробовать создать его после примера «Reading and writing to a SAFEARRAY», используя константы org.eclipse.swt.internal.win32.OS. Но это похоже только на char[].

Другой источник вдохновения для создания соответствующего SAFEARRAY:

class SafeArray of project com4j (и связанный с ним класс, как Variant)

+0

Спасибо, мне не пришло в голову, что я могу отправить массив вариантов. Я попробую и вернусь к вам. –

+0

Что касается SAFEARRAY, я не думаю, что мне нужен SAFEARRAY, поскольку COM IDL будет указывать, когда ему это нужно, не так ли? Я видел IDL функций, требующих SAFEARRAY; в этом конкретном состоянии IDL мне нужен вариант. В любом случае, я попробую и вернусь к вам. –

+0

На самом деле, теперь я не уверен; это на самом деле может быть SAFEARRAY. Hrmmm. –