Java SWT взаимодействует с COM - помещает float [] в Variant? - PullRequest
8 голосов
/ 20 августа 2009

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

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

Проблема в последней строке: как передать массив с плавающей точкой стороннему COM-объекту? HELP!

Ответы [ 3 ]

1 голос
/ 25 октября 2009

Вам нужно передать массив с плавающей точкой. В терминах COM это означает s VARIANT с vt, установленным в VT_R4 | VT_ARRAY. Массив вариантов может не работать, так как в документе не сказано, что он может принимать массив вариантов (VT_VARIANT | VT_ARRAY). В Java вы должны иметь возможность использовать float [] в качестве типа параметра. Если нет, вы всегда можете вызвать Windows API для создания безопасного массива нужного типа .

0 голосов
/ 23 августа 2009

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

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, вы можете попробовать создать его после примера " Чтение и запись в SAFEARRAY ", используя константы org.eclipse.swt.internal.win32.OS. Но, похоже, только для char[].

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

класс SafeArray проекта com4j (и связанный с ним класс, например Variant)

0 голосов
/ 23 августа 2009

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

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

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

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