使用 System.load("path/to/opencv") 加载 OpenCV 在 Windows 上失败,在 Linux 上工作

问题描述 投票:0回答:1

我正在发布一个使用 OpenCV 作为单个可执行 jar 的应用程序。为了避免最终用户需要在自己的系统上下载 OpenCV,OpenCV 二进制文件存储在 jar 内,并提取到临时文件,并使用

System.load()
和临时文件路径加载,按照 this stackoverflow post suggest,如下如下:

public class NativeLibraryLoader {

    private static Logger logger = LogManager.getLogger();

    /**
     * This is a safe way to load a native library from a jar, assuming that library
     * is inside your resource director/classpath.
     */
    public static void loadLibraryFromJar(String libraryName) throws IOException {
        logger.debug("Loading native library %s".formatted(libraryName));
        InputStream is = NativeLibraryLoader.class.getResourceAsStream("/" + libraryName);
        File library = File.createTempFile("jni-temp-file", "tmp");
        library.deleteOnExit();
        try (OutputStream os = new FileOutputStream(library)) {
            logger.debug("Copying library input stream to temp file " + library.getPath());
            os.write(is.readAllBytes());
        }
        logger.debug("Loading library " + library.getPath());
        System.load(library.getPath().replace("\\", "/"));
    }

}

当我加载

opencv_490.so
时,此方法在Linux上运行得很好。库加载,我可以使用 OpenCV。但是,当使用
opencv_490.dll
在 Windows 上运行相同的命令时,它找不到该库,并且我得到 UnsatisfiedLink。
loadLibraryFromJar
方法在调用
System.load()
时抛出错误,并在单元测试期间产生以下错误:

[ERROR] Tests run: 2, Failures: 0, Errors: 2, Skipped: 0, Time elapsed: 0.188 s <<< FAILURE! - in com.toughdata.autogrowth.TestOpenCVCaptchaProcessor
[ERROR] testSolveRotateCaptchaIsKnownValue  Time elapsed: 0.187 s  <<< ERROR!
java.lang.UnsatisfiedLinkError: C:\Users\greg\AppData\Local\Temp\jni-temp-file78576686543799615tmp: Can't find dependent libraries
        at com.toughdata.autogrowth.TestOpenCVCaptchaProcessor.testSolveRotateCaptchaIsKnownValue(TestOpenCVCaptchaProcessor.java:16)

[ERROR] testSolvePuzzleCaptchaIsKnownValue  Time elapsed: 0 s  <<< ERROR!
java.lang.NoClassDefFoundError: Could not initialize class com.toughdata.autogrowth.automation.captcha.OpenCVCaptchaProcessor
        at com.toughdata.autogrowth.TestOpenCVCaptchaProcessor.testSolvePuzzleCaptchaIsKnownValue(TestOpenCVCaptchaProcessor.java:24)
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.UnsatisfiedLinkError: C:\Users\greg\AppData\Local\Temp\jni-temp-file78576686543799615tmp: Can't find dependent libraries [in thread "main"]
        at com.toughdata.autogrowth.TestOpenCVCaptchaProcessor.testSolveRotateCaptchaIsKnownValue(TestOpenCVCaptchaProcessor.java:16)

[INFO]
[INFO] Results:
[INFO]
[ERROR] Errors:
[ERROR]   TestOpenCVCaptchaProcessor.testSolvePuzzleCaptchaIsKnownValue:24 NoClassDefFound
[ERROR]   TestOpenCVCaptchaProcessor.testSolveRotateCaptchaIsKnownValue:16 » UnsatisfiedLink
[INFO]
[ERROR] Tests run: 19, Failures: 0, Errors: 2, Skipped: 8
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  13.035 s
[INFO] Finished at: 2024-03-11T09:04:46+11:00
[INFO] ------------------------------------------------------------------------

我可以看到临时文件已创建,并且库已提取并写入临时文件。有谁知道什么可能导致在 Linux 上正常工作时对

System.load()
的调用在 Windows 上失败?

java opencv jar java-native-interface executable-jar
1个回答
0
投票

好吧,我能弄清楚这一点。在创建临时文件时,我冒险将

tmp
扩展名更改为
.dll
。事实证明,Windows 希望库以
.dll
文件扩展名结尾。 Linux 不关心你的库是否以
.so
结尾,但在 Windows 上它们必须以
.dll

结尾
© www.soinside.com 2019 - 2024. All rights reserved.