#scala #opencv #playframework #sbt
#scala #opencv #playframework #sbt
Вопрос:
Я запускаю приложение play Framework, используя opencv с scala. При запуске приложения я получаю UNSATISFIEDLINK Error из VideoCapture, так как же я могу правильно загрузить библиотеку opencv?
Когда я запускаю тест с использованием классов из opencv, все работает правильно. Я всегда устанавливаю System.LoadLibrary (Core.NATIVE_LIBRARY_NAME) и правильно определяю параметр java.path.library. Но когда я запускаю приложение play, это работает не так, как с тестами.
Судя по другим сообщениям, люди решали эту проблему, используя абстрактный класс GlobalSetting из play и загружая библиотеку методом BeforeStart(). Но это устарело, и теперь Play рекомендует выполнить обязательную привязку. Я уже пытался создать загрузчик, который будет запускаться первым при запуске сервера, на который я загружаю библиотеку таким же образом, как я запускаю тесты. Код в этом классе запускается первым, как и должно быть, но это не спасает мою проблему.
Я также пытался загрузить библиотеку в разные имеющиеся у меня контроллеры и класс, в котором я использую VideoCapture (), но ничего не работает. Более того, я попытался создать задачу sbt, в которой я загружал библиотеку, но не сработало.
class EagerLoaderModule extends AbstractModule {
override def configure(): Unit = bind(classOf[StartUpService]).asEagerSingleton()
}
final class StartUpService {
def loadedLibs: Seq[String] = {
val libs = classOf[ClassLoader].getDeclaredField("loadedLibraryNames")
libs.setAccessible(true)
import scala.collection.JavaConverters._
libs.get(ClassLoader.getSystemClassLoader)
.asInstanceOf[java.util.Vector[String]]
.asScala
}
def loadOpenCVOnDemand(): Unit = {
val isLoaded = loadedLibs.map(str => str contains "opencv").reduce((x, y) => x || y)
if(!isLoaded) {
try {
println("hey there dude")
System.loadLibrary(Core.NATIVE_LIBRARY_NAME)
println("ksdfjsdkfh")
} catch {
case e: UnsatisfiedLinkError =>
println("Loading Library OPENCV")
System.loadLibrary("opencv_java345")
// e.printStackTrace()
}
}
}
loadOpenCVOnDemand()
}
Ошибка, которую я получаю, такова: java.lang.Ошибка неудовлетворенной ссылки: org.opencv.videoio.VideoCapture.VideoCapture_1(Ljava / lang / String;) J и я знаю, что это потому, что System.LoadLibrary (Core.NATIVE_LIBRARY_NAME) работает некорректно, но как я могу заставить это работать или где я должен это настроить, чтобы приложение правильно загружало библиотеку?
Ответ №1:
Поддержка встроенной библиотеки в режиме разработки (play run) # 2212 определяет проблему как:
Когда libopencv_java загружается из управляемого кода play-sbt-plugin, он загружается в ReloadableClassLoader, но opencv-*.jar уже находится в PlayDependencyClassLoader. Похоже, JDK не нравится такое разделение. Итак, встроенная библиотека и ее аналог java должны (must?) находиться в том же загрузчике классов. Одним из решений является удаление вызовов load / LoadLibrary из проекта на основе Play в отдельный jar, а затем добавление этого jar в качестве зависимости проекта.
Для обхода попробуйте импортировать play-native-loader
libraryDependencies = "com.typesafe.play" %% "play-native-loader" % "1.0.0"
и загрузите библиотеку с помощью NativeLoader.load
вместо System.loadLibrary
вот так
NativeLoader.load(Core.NATIVE_LIBRARY_NAME)
play-opencv-native-example является рабочим примером.