zoukankan      html  css  js  c++  java
  • JNI调用Cython生成库‘undefined symbol: PyInit_’问题

    最近项目需要提升所有 Python 算法的执行时间,并给 Java 框架调用,根据 Python一键转Jar包,Java调用Python新姿势!的思路可以用 Cython 将 Python 代码转换为 C 代码再编译为动态连接库 (so / dll),提升 Python 代码执行速度。同时提供 Java Native 接口以供 Java 框架调用。

    问题

    但在根据刚刚所提博文进行复现时,出现了一个老大难问题,一直都没什么头绪

    Exception in thread "main" java.lang.UnsatisfiedLinkError: /path/libTest.cpython-36m-x86_64-linux-gnu.so: /path/libTest.cpython-36m-x86_64-linux-gnu.so: undefined symbol: PyInit_Test
    	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    	at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
    	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
    	at java.lang.Runtime.load0(Runtime.java:809)
    	at java.lang.System.load(System.java:1086)
    	at Test.<clinit>(Test.java:6)
    	at Demo.main(Demo.java:3)
    

    直到看到这篇博客 解決 Linux 上 C/C++ 的 undefined symbol 或 undefined reference,可以通过 nm -D LIBRARY_FILE 来查看动态代码段的相关符号 (symbol),输出信息如下

    0000000000004a10 T Java_Test_uninitModule
    0000000000004a20 T Java_Test_upperFunction
                     ......
                     U PyImport_ImportModule
                     U PyInit_Test
    00000000000042e7 T PyInit_libTest
                     ......
    

    其中,T 表示全局/局部符号,U 表示为未定义的符号。

    原因

    也就是说,这个 PyInit_Test 函数未定义,但 PyInit_libTest 却定义了,明明在 main.c 中没有定义这个lib函数,唯一出现的地方就是在编译文件 setup.py

    extensions = [Extension("libTest", sourcefiles,
      include_dirs=['/usr/lib/jvm/java-8-oracle/include/',
        '/usr/lib/jvm/java-8-oracle/include/linux/',
        '/python/path/include/python3.6m/'],
      library_dirs=['/python/path/lib/'],
      libraries=['python3.6m'])]
    

    第一个参数是 name,表示的是这个 extension 的全称,而之后的调用就会依托这个名字,同时在 main.cPyInit_ 之后接的是该模块的名称。也就是说,当这两个名称相同的时候,Cython 才能成功编译这个模块。

    解决方案

    因此将参数 name"libTest" 替换为 "Test",问题解决。

    重新用 nm -D Test.so 来查看,可以看到 PyInit_Test这个函数已定义,收工~

    00000000000042b7 T PyInit_Test
    
  • 相关阅读:
    对称加密算法:替代算法与置换算法
    cin与getline
    延迟任务实现方式
    @Validated校验
    mac 终端 常用命令
    IOS和Android的区别[转]
    [IOS] NSIndexPath , NSIndexSet , NSRange 之间的区别比较
    [IOS]iphone开发之UIImage应用与内存管理,UIImage加载图像方法
    CorePlot SDK的安装以及应用
    [IOS] iphone 之 横屏和自动旋转
  • 原文地址:https://www.cnblogs.com/IO382/p/13196591.html
Copyright © 2011-2022 走看看