在Linux环境下使用gfortran编译器生成fortran语言的.so共享对象文件 并使用JNA调用 带参方法

  • 1 致谢和参考文章
    • 1.1 致谢
    • 1.2 参考文章
  • 2 环境介绍
  • 3 整体思路
  • 4 具体步骤
    • 4.1 环境准备
    • 4.2 编写测试的fotran源文件
    • 4.3 在linux环境中编译fortran源文件
    • 4.4 将生成的.so放置于linux的某个绝对路径下,为JNA调用时的路径提供依据
    • 4.5 编写JNA调用.so测试程序 - 部分主要代码
    • 4.6 执行测试程序
  • 5 注意事项和坑
    • 5.1 传入参数未使用引用类型(报错)
    • 5.2 方法返回值使用引用类型, 并用实现类对其进行 向下强制转型(报错)

1 致谢和参考文章

1.1 致谢

Godzilla_BB

1.2 参考文章

CentOS下安装gfortran

linux下gfortran生成so文件

Linux查看.so文件中函数

JNA调用.dll或.so动态链接库文件

fortran 和 java_JNA实现Java调用Fortran

2 环境介绍

Java开发环境 IDEA-2018.3

Fortran开发环境 VS2019-community + XE2020

Linux环境 VMware 15 中的 centos 7

3 整体思路

① 准备好linux环境,并安装gfortran。

② 编写好 待测试/使用的fortran源文件。

③ 将fortran源文件 在linux系统中 使用gfortran 编译成.so共享库文件,并放置于某个绝对路径下。

④ 使用JNA编写java调用.so文件的测试程序。

4 具体步骤

4.1 环境准备

准备一台虚拟机,并安装Centos7操作系统。

gfortran安装 (centos环境,以root身份运行,终端输入命令无需sudo)

安装命令: yum install gcc-gfortran

测试是否安装成功:gfortran -v

4.2 编写测试的fotran源文件

测试源文件为 Source2.f90 (封装了一个简单的加法函数)

integer function add_so(first, second)implicit noneinteger first,secondadd_so = first + secondreturnend function

4.3 在linux环境中编译fortran源文件

将源文件Source2.f90编译成 add.so的共享对象文件

编译命令:gfortran -shared -fPIC -o add.so Source2.f90

编译成功后 输出的add.so文件

查看并验证add.so中暴露的端口是否有源文件的add_so方法。

注意,暴露的方法默认会给源文件中定义的方法增加一个下划线,即:方法名变成 add_so_

查看命令: nm -D add.so

4.4 将生成的.so放置于linux的某个绝对路径下,为JNA调用时的路径提供依据

测试存放路径为 /root/user/add.so

4.5 编写JNA调用.so测试程序 - 部分主要代码

使用的JNA的Maven仓库依赖

     <!--JNA相关依赖--><dependency><groupId>net.java.dev.jna</groupId><artifactId>jna</artifactId><version>4.2.2</version></dependency>

为将调用的.so文件编写接口文件SoTest.java

注意必须使用抽象父类ByReference,使用实现子类会发生错误

注意.so文件暴露的接口方法后 默认要增加一个下划线,即:add_so_

import com.sun.jna.Library;
import com.sun.jna.ptr.ByReference;public interface SoTest extends Library {//    注意必须使用抽象父类ByReference,默认情况下,fortran使用引用参数
//    使用IntByReference实现类等会发生错误int add_so_(ByReference a, ByReference b);
//    int add_so_(int a, int b);
}

测试.so文件的程序代码(注意匹配.so文件的路径)
测试时若页面返回 996 则表示调用成功

 /*** linux环境测试调用简单的.so文件* @return*/@RequestMapping(value = "/soTest")public String soTest(){//        String libName = "mytest";String libName = "/root/user/add.so";SoTest soTest = (SoTest) Native.loadLibrary(libName, SoTest.class);//        带参数的test_soIntByReference a = new IntByReference(995);IntByReference b = new IntByReference(1);int result = soTest.add_so_(a, b);System.out.println("操作完成");return "result = " + result;}

4.6 执行测试程序

测试程序本身处于一个Springboot的 web 项目中,结果将以页面形式返回。

返回结果

最终输出996, 使用 JNA 调用带参数的 fortran语言的.so文件 成功。

5 注意事项和坑

在为fortran调用的函数而编写的 java接口文件中,即SoTest.java中 【详见4.5】

5.1 传入参数未使用引用类型(报错)

针对带有参数的方法,必须使用引用类型。否则会发生致命错误 导致 Failed to write core dump

演示的错误代码 - 传入参数未使用引用类型

public interface SoTest extends Library {//    注意必须使用抽象父类ByReference,默认情况下,fortran使用引用参数
//    使用IntByReference实现类等会发生错误
//    int add_so_(ByReference a, ByReference b);int add_so_(int a, int b);
}

具体错误如下

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f3943dfe6a5, pid=3947, tid=0x00007f3968fa9700
#
# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [add.so+0x6a5]  add_so_+0x10
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping,
try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /root/user/******/hs_err_pid3947.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
已放弃(吐核)

5.2 方法返回值使用引用类型, 并用实现类对其进行 向下强制转型(报错)

针对为fortran文件编写的java接口中,暴露的方法返回类型 需要使用 基本类型接收 (相对于引用类型而言) , 否则会发生抽象引用类型无法实例化,缺少一个无参构造函数的错误。

演示的错误代码 - 方法返回值使用引用类型,并用实现类对其进行 向下强制转型

接口定义 SoTest.java

public interface SoTest extends Library {//    注意必须使用抽象父类ByReference,默认情况下,fortran使用引用参数
//    使用IntByReference实现类等会发生错误
//    int add_so_(ByReference a, ByReference b);
//    int add_so_(int a, int b);ByReference add_so_(ByReference a, ByReference b);
}

测试程序的接收, 用实现类对抽象引用类型强制向下转型发生错误

 /*** linux环境测试调用简单的.so文件* @return*/@RequestMapping(value = "/soTest")public String soTest(){//        String libName = "mytest";String libName = "/root/user/add.so";SoTest soTest = (SoTest) Native.loadLibrary(libName, SoTest.class);//        带参数的test_soIntByReference a = new IntByReference(995);IntByReference b = new IntByReference(1);System.out.println("a = " + a.getValue());System.out.println("b = " + b.getValue());//        int result = soTest.add_so_(a, b);
//        int result = soTest.add_so_(995, 1);int result = ((IntByReference)soTest.add_so_(a,b)).getValue();System.out.println("操作完成");return "result = " + result;}

具体错误 - 部分

ERROR 4173 --- [nio-9010-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    :
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw
exception [Request processing failed; nested exception is
java.lang.IllegalArgumentException: Can't create an instance of class
com.sun.jna.ptr.ByReference, requires a no-arg constructor:
java.lang.InstantiationException: com.sun.jna.ptr.ByReference] with root causejava.lang.IllegalArgumentException: Can't create an instance of class
com.sun.jna.ptr.ByReference, requires a no-arg constructor:
java.lang.InstantiationException: com.sun.jna.ptr.ByReferenceat com.sun.jna.NativeMappedConverter.defaultValue(NativeMappedConverter.java:55) ~[jna-4.2.2.jar!/:4.2.2 (b0)]at com.sun.jna.NativeMappedConverter.<init>(NativeMappedConverter.java:44) ~[jna-4.2.2.jar!/:4.2.2 (b0)]at com.sun.jna.NativeMappedConverter.getInstance(NativeMappedConverter.java:32) ~[jna-4.2.2.jar!/:4.2.2 (b0)]at com.sun.jna.Function.invoke(Function.java:312) ~[jna-4.2.2.jar!/:4.2.2 (b0)]at com.sun.jna.Library$Handler.invoke(Library.java:236) ~[jna-4.2.2.jar!/:4.2.2 (b0)]at com.sun.proxy.$Proxy56.add_so_(Unknown Source) ~[na:na]....等等信息

在Linux环境下使用gfortran编译器生成fortran语言的.so共享对象文件 并使用JNA调用 带参方法相关推荐

  1. Linux环境下静态库的生成和使用 (.a文件)

    这一阵子的工作用到了linux,也用到了linux的静态库和动态库.正好对这一块儿一直不明白,趁此机会学习了一下.以下是笔记.先说一说linux下静态库的生成和使用方法. An archive (or ...

  2. linux环境下的c编程指南,C语言Socket简单编程指南PDF

    1.介绍 Socket 编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措? ...

  3. linux环境下pv吃水果问题c语言,用pv操作实现 吃水果问题(C++语言)

    /** 作者:wwj 时间:2012/4/12 功能:实现吃水果问题 **题目内容:桌子有一只盘子,只允许放一个水果,父亲专向盘子放苹果,母亲专向盘子放桔子 儿子专等吃盘子的桔子,女儿专等吃盘子的苹果 ...

  4. linux下的python安装,linux环境下的python安装过程

    一.下载python源码包 打开ubuntu下的shell终端,通过wget命令下载python源码包,如下图所示: wget https://www.python.org/ftp/python/3. ...

  5. linux环境下Ncurses实现贪吃蛇游戏

    游戏说明: linux环境下基于Ncurses图形库的C语言小游戏. Ncurses介绍: Ncurses(new curses)是一套编程库,它提供了一系列的函数以便使用者调用它们去生成基于文本的用 ...

  6. linux websphere 端口号,Linux环境下配置websphere7.0的一些命令

    Linux环境下配置websphere7.0的一些命令! 1.创建概要文件 通过命令行建立Dmgr服务器,进入${WAS_Home}/bin目录,运行 ./manageprofiles.sh -cre ...

  7. Linux环境下,通过shell脚本实现一键部署MySQL,并支持多种类型

    Linux环境下一键部署MySQL脚本,支持多种类型 前言 一.使用前须知 二.使用方法 三.shell脚本内容 总结 前言   MySQL是目前最流行的关系型数据库管理系统之一,属于 Oracle ...

  8. 编译高性能linux so库,关于如何在linux环境下生成a库和so库(改,附图)-Go语言中文社区...

    一般linux环境下的链接库分为a库和so库,分别表示静态链接库和动态链接库,其作用是把C程序编译好做成一种可执行链接文件,c主程序文件调用这些程序的函数接口是可以使用a库或so库,在主程序中只需要i ...

  9. linux环境生成weblogic密钥,Linux环境下创建weblogic服务.doc

    Linux环境下创建weblogic服务 weblogic用户登录10.218.0.25. 执行一下命令 cd /bea/weblogic92/common/bin ./config.sh 选择创建一 ...

最新文章

  1. 【目标检测】yolo系列:从yolov1到yolov5之YOLOv1详解及复现
  2. 保护模式下GDTR,LDTR,全局描述符表,局部描述符表和选择器的关系
  3. java中实现对list的模糊查询
  4. 每天一道LeetCode-----只可能有'.'和'*'的字符串正则匹配
  5. pytest 15 fixture之autouse=True
  6. 单片机断电后静态存储区里面还有数据吗_单片机启动流程和存储架构详解
  7. cocos2d-x for xna创建动画-人物行走
  8. Python风格总结: 复制列表
  9. [转] CPU GPU TPU
  10. ubuntu 12 04下安装JDK7
  11. C/C++与lua实现互调
  12. halcon教程- 边缘检测 亚像素边缘提取 轮廓提取
  13. 使用微软官方方法制作纯净WinPE
  14. 如何调用TUIO中的源码
  15. mysql插入表情_向MySQL数据库中插入带emoji表情符的数据时报错
  16. 认知电子战 (1.1):传统电子战
  17. python画图横坐标_python画图把时间作为横坐标的方法
  18. base64照片压缩
  19. 关于项目采购管理,这些你需要知道
  20. PRML:Pattern Recognition And Machine Learning 相关资料整理与下载

热门文章

  1. 【数据库数据恢复】Oracle数据库文件出现坏块报错的数据恢复案例
  2. Python-字符串编码
  3. 关注镇坪华南虎照片事件有感
  4. 亚马逊、shopee、Lazada、ebay、速卖通补单不安全?刷单要注意这4点
  5. linux中的进程与线程,linux中进程和线程的区别是什么
  6. Android设备获取USB扫码枪扫描的内容与可能遇到的问题解决
  7. 使用阿里EasyExcel实现上传下载、导入导出Excel
  8. 硬盘安装+游戏功能+虚拟机XP-80分钟打造娱乐型ubuntu7.10[转]
  9. java-----------GUI菜单设计
  10. [Eclipse插件开发-001] SWT/JFACE布局入门总结