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

    https://mp.weixin.qq.com/s/C9iktVr4hnQ8lM0CiWtedQ 简单介绍CanHaveBuiltInDevices的实现. 1. HasBuiltInDeviceP ...

  2. Java实现蓝桥杯基础练习特殊回文数

    基础练习 特殊回文数 时间限制:1.0s 内存限制:512.0MB 提交此题 锦囊1 锦囊2 问题描述 123321是一个非常特殊的数,它从左边读和从右边读是一样的. 输入一个正整数n, 编程求所有这 ...

  3. 第四届蓝桥杯JavaC组国(决)赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.好好学习 汤姆跟爷爷来中国旅游.一天,他帮助中国的小朋友贴标语.他负责贴的标语是分别写在四块红纸上的四个大字:"好.好.学. ...

  4. Netty源码学习系列之4-ServerBootstrap的bind方法

    前言 今天研究ServerBootstrap的bind方法,该方法可以说是netty的重中之重.核心中的核心.前两节的NioEventLoopGroup和ServerBootstrap的初始化就是为b ...

  5. 运行npm run start 提示primordials is not defined

    下载https://github.com/ant-motion/editor-list 执行 npm install npm start gulp构建时报错. 原因:安装gulp版本与node版本不兼 ...

  6. 大型Electron应用本地数据库技术选型

    开发一个大型Electron的应用,或许需要在客户端存储大量的数据,比如聊天应用或邮件客户端 可选的客户端数据库方案看似很多,但一一对比下来,最优解只有一个 接下来我们就一起来经历一下这个技术选型的过 ...

  7. 创建sudo -i免密权限账户

    项目原因,服务器需要创建普通用户,但又不能让用户拿到root密码. 创建用户 [root@bogon ~]# groupadd connect [root@bogon ~]# useradd -g c ...

  8. Mybatis反射修改SQL值

    Mybatis反射修改SQL值 某一些情况下我们需要动态的改变Mybtis的执行的sql语句,有两种方法:1)使用拦截器,2)使用反射,拦截器的比较简单点,这里使用反射实现一次,有一点小坑,记录一下: ...

  9. 小师妹学JavaIO之:Buffer和Buff

    目录 简介 Buffer是什么 Buffer进阶 创建Buffer Direct VS non-Direct Buffer的日常操作 向Buffer写数据 从Buffer读数据 rewind Buff ...

  10. .Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上)

    前言 上一篇[.Net Core微服务入门全纪录(一)--项目搭建]讲到要做到服务的灵活伸缩,那么需要有一种机制来实现它,这个机制就是服务注册与发现.当然这也并不是必要的,如果你的服务实例很少,并且很 ...