最近项目需要提升所有 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

JNI调用Cython生成库‘undefined symbol: PyInit_’问题的更多相关文章

  1. JAVA程序通过JNI调用C/C++库

    java程序如何调用c/c++库中的函数主要分为三个步骤: 1. 加载库文件. System.loadLibrary 2. 找到函数( java函数<----映射---->c函数 ) 3. ...

  2. Linux 动态库 undefined symbol 原因定位与解决方法

    在使用动态库开发部署时,遇到最多的问题可能就是 undefined symbol 了,导致这个出现这个问题的原因有多种多样,快速找到原因,采用对应的方法解决是本文写作的目的. 可能的原因 依赖库未找到 ...

  3. JNI调用so动态库

    1.编写native接口 package org.demo; public class JniDemo { public static native int bmp2fea(byte[] bmp, b ...

  4. Java採用JNI调用VC++生成的dll(Java与C++交互)

    应项目需求,须要android调用java,java再调用C++实现android一个图片匹配的功能,我们作为java组须要和C++和Android进行交互.以下是java和C++採用JNI的方式进行 ...

  5. java调用c++生成的动态和静态库时遇到的问题

    java.lang.UnsatisfiedLinkError: no jacob in java.library.path -Djava.library.path 关于java用jni调用 dll动态 ...

  6. [置顶] android利用jni调用第三方库——第三篇——编写库android程序整合第三方库libhello.so到自己的库libhelloword.so

    0:前言: 在第二篇中,我们主要介绍了丙方android公司利用乙方C++公司给的动态库,直接调用库中的方法,但是这样方式受限于: 乙方C++公司开发的动态库是否符合jni的规范,如果不规范,则不能直 ...

  7. 利用android studio 生成 JNI需要的动态库so文件

    JNI:  Java Native Interface,  提供了java语言和其他语言(例如c和c++)进行相互调用的方式. 本文是用java调用c生成的so模式.其中,编译so文件过程如下: 1) ...

  8. c++调用matlab生成的Dll动态连接库

    点击打开链接http://download.csdn.net/detail/nuptboyzhb/4228429 c++调用matlab生成的Dll动态连接库 实验平台:   matlab 7.0(R ...

  9. [置顶] android利用jni调用第三方库——第二篇——编写库android程序直接调用第三方库libhello.so

    0:前言 1:本文主要作为丙方android公司的身份来写 2:作者有不对的地方,请指出,谢谢 [第一篇:android利用jni调用第三方库——编写库libhello.so] [第二篇:androi ...

随机推荐

  1. PriorityBlockingQueue 和 Executors.newCachedThreadPool()

    1.PriorityBlockingQueue里面存储的对象必须是实现Comparable接口. 2.队列通过这个接口的compare方法确定对象的优先级priority. 规则是:当前和其他对象比较 ...

  2. ionic3跳转页面的方法

    ionic3很好很强大,有人喷有人赞.不想参与其中,个人认为如果能很好的满足需求,好坏都是无所谓的,最合适的才是最好的.总结下最近使用ionic3的一些知识点,方便以后查询.多句嘴:会ionic3和只 ...

  3. Java实现 LeetCode 816 模糊坐标(暴力)

    816. 模糊坐标 我们有一些二维坐标,如 "(1, 3)" 或 "(2, 0.5)",然后我们移除所有逗号,小数点和空格,得到一个字符串S.返回所有可能的原始 ...

  4. Java 第十一届 蓝桥杯 省模拟赛 第十层的二叉树

    一棵10层的二叉树,最多包含多少个结点? 注意当一棵二叉树只有一个结点时为一层. 答案提交 这是一道结果填空的题,你只需要算出结果后提交即可.本题的结果为一个整数,在提交答案时只填写这个整数,填写多余 ...

  5. Java实现 LeetCode 258 各位相加

    258. 各位相加 给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数. 示例: 输入: 38 输出: 2 解释: 各位相加的过程为:3 + 8 = 11, 1 + 1 = 2. 由 ...

  6. java实现第六届蓝桥杯熊怪吃核桃

    熊怪吃核桃 题目描述 森林里有一只熊怪,很爱吃核桃.不过它有个习惯,每次都把找到的核桃分成相等的两份,吃掉一份,留一份.如果不能等分,熊怪就会扔掉一个核桃再分.第二天再继续这个过程,直到最后剩一个核桃 ...

  7. /etc/alternatives

    如何安装一个可执行程序 一般来说我们一个可执行程序,可能在多个路径下,比如在opt路径下,或者在自己的home下. 当要达到在系统的任意路径下敲击该命令,都可执行的话,一般要将该可执行命令的路径加入到 ...

  8. rpm安装Clickhouse

    1. 下载相关安装包 在opt目录下创建clickhouse目录,方便下载文件 Cd /opt/clickhouse  一次执行一下命令 ① wget --content-disposition ht ...

  9. 我的Dos笔记

    DOS笔记:DOS是英文Disk Operating System的缩写,意思是“磁盘操作系统”[drive:][path][filename] 指定要列出的驱动器.目录和/或文件.    /A   ...

  10. 使用Aspose.word (Java) 填充word文档数据(包含图片填充)

    Aspose填充word数据 本文介绍了如何使用aspose进行word文档的生成,并提供了工具类供参考. 有问题欢迎 call 微信:905369866,小弟尽力而为..毕竟这玩意没吃透. 目录 A ...