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
    
  • 相关阅读:
    __module__ 和 __class__
    __str__ 和 __repr
    __getitem__ __setitem__ __delitem__ 使用
    授权
    __getattr__ __delattr__ __setattr__ __getattribute__使用(重写python提供的错误信息)
    __import__
    hasattr getattr setattr delattr --> (反射)
    类三大特性(继承 多态 封装)
    静态方法@staticmethod
    类方法@classmethod
  • 原文地址:https://www.cnblogs.com/IO382/p/13196591.html
Copyright © 2011-2022 走看看