Eclipse RCP + Native Code

1 отговора 0 прегледа
#1

Eclipse RCP + Native Code

Здравейте,

в момента пиша една Eclipse Rich Client Platform апликация и се сблъсках с проблем, на който след доста ровене по документации, блогове и форуми все още не мога да намеря разрешение. Реших да попитам и вас в случай, че някой е имал подобна ситуация.

Положението е следното. Един от плъгиновете, които пиша за апликацията, използва third party библиотека. Тя се състои от един .jar и няколко dll-а. Част от класовете в jar-а ползват въпросните dll чрез JNI, но имам само приблизителна представа какво точно се случва, понеже нямам достъп до кода. Eclipse-проектът на плъгина изглежда горе-долу така:

+ src
+ lib
|- library.jar
- a.dll
- b.dll
- c.lib

library.jar е в Build Path-a, а dll-овете са декларирани в манифеста на плъгина:

Bundle-NativeCode: а.dll ; b.dll ; c.lib ; osname=win32 ; processor=x86

Кодът компилира, но щом се опитам да инстанциирам някой клас от library.jar, винаги получавам ClassNotFoundException. Както изглежда, самите dll-ове са познати на системата, понеже System.loadLibrary("...") работи. Но ClassLoader-а на плъгина не намира класовете от library.jar. Някой знае ли какво пропускам?!

Мерси и приятна работа на всички!

Отговор
в отговор на eos #2

Re: Eclipse RCP + Native Code

Ок, открих решението. В случай, че някой някога запецне на същото място:

Първо, library.jar трябва изрично да се добави в ClassPath-а на плъгина (в MANIFEST.MF):

Bundle-ClassPath: lib/library.jar,
.

Второ, Bundle-NativeCode не е достатъчен сам по-себе си, поне в моя случай.
Тази директива позволява на плъгините да ползват нативни библиотеки без да трябва да се манипулира java.library.path. Всички dll файлове, декларирани в тази директива, стават видими и могат да бъдат заредени с System.loadLibrary(), т.е. директно по име.

Проблемът е, когато има повече от един dll-а, които имат dependencies помежду си. Ако най-напред се опитаме да заредим нативна библиотека, която има dependency, Windows няма да знае къде да намери тази dependency - информацията за това е известна само на виртуалната машина. Така че това веднага ще доведе до грешка. Ако обаче първо сме заредили библиотеката, която удовлетворява необходимата dependency, Windows просто ще установи, че вече е била заредена и няма да се оплаква (нативните библиотеки могат да бъдат заредени само еднократно).

Така че в Активатора на пългина, в метода start(BundleContext context) добавих:

System.loadLibrary("а");
System.loadLibrary("b");

и всичко тръгна по мед и масло.

Тъпа история, но като се налага...

Поздрави.

Отговор