我正在使用Play Framework 2.1编写一个webapp,它使用OpenCV(2.4.6)库。我编译OpenCV并获得最终的.jar没有任何问题,但有一句话让我在the Java/Scala tutorial担心OpenCV:
请注意对
System.loadLibrary(Core.NATIVE_LIBRARY_NAME)
的通话。这个 在使用之前,每个Java进程必须执行一次命令 任何原生的OpenCV方法。如果你不打电话,你会得到 不满意的链接错误。如果您尝试加载,也会出错 OpenCV已经加载。
我知道Play Framework是多线程的,线程在请求之间重用。有没有办法让我在每个单独的线程产生时调用loadLibrary
函数?或者我误解了线程池的工作方式,我应该根据请求加载一次库?这里的正确方法是什么?
[编辑:]我发现我可以将System.loadLibrary
代码放在全局配置类中,这将使所有线程共享库。该库不是线程安全的,所以我认为如果我这样做只是偶然发生......
答案 0 :(得分:0)
似乎没有问题 - “每个Java 进程必须执行一次此命令” - 只需在应用程序启动时调用一次就可以了,您不必担心不同的线程。
奖励:可以检查库是否已经加载(即使它是完全没必要的),即:
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) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME)
}
}
另一个问题是,是否可以同时调用本机库的函数。在OpenCV中,它根本不是问题:
当前的OpenCV实现完全可以重新输入。那就是 相同的函数,类实例的相同常量方法,或者 可以调用不同类实例的相同非常量方法 来自不同的线程。此外,可以使用相同的cv :: Mat 不同的线程因为引用计数操作使用了 特定于体系结构的原子指令。