zoukankan      html  css  js  c++  java
  • Java调用动态链接库so文件(传参以及处理返回值问题)

    刚来到公司,屁股还没坐稳,老板把我叫到办公室,就让我做一个小程序。我瞬间懵逼了。对小程序一窍不通,还好通过学习小程序视频,两天的时间就做了一个云开发的小程序,但是领导不想核心的代码被别人看到,给了我一个dll文件。找了大量的资料,还是用Java做吧,于是又快速的用Java搭建了一个后台,测试了一下,发现dll调用成功了,但是在发布到服务器上的时候,dll文件又不行了,又找方法。发现so文件和dll文件一样,都是打包生成的动态链接库,于是就在服务器上测试调用so文件,在调用so文件的时候出现了很多的问题,例如so文件生成失败、调用so文件找不到里面的方法、返回值出现乱码等。

    一、生成so文件(Limux下操作)

      1.把.h文件和.cpp文件放到一起(随意了想咋放都行 执行命令的时候地址写对就好)

        test.h文件只写.cpp文件里面的方法名

    void Test01();
    

          test.cpp文件

    #include <stdio.h>
    #include "test.h"
     
    void Test01()
    {
        printf("TestA func
    ");
     }
    

      

    生成so文件的命令(在文件的路径下执行)

    g++ test.cpp -fPIC -shared -o libtest.so
    

      so文件以lib开头(lib**.so)

       这种方式生成的so文件有时在Java后端调用的时候报找不到指定方法的错误。然后找了好久找到一个方法给我解决了这个问题(看第二种生成so文件的方式)。(如果这个方法你们不适用,那就另找解决方式吧)

      2.不要.h文件了直接用.cpp文件

      

    1 #include <stdio.h>
    2 #include "test.h"
    3  
    4 extern "C" void Test01()
    5 {
    6     printf("TestA func
    ");
    7  }

    方法的前面以 extern "C" 开头,用这种方式对方法进行声明。

    2.通过Java的jna包调用so文件进行传参(直接上代码)

    public interface CLibrary extends Library {
               
                // DLL文件默认路径为项目根目录,若DLL文件存放在项目外,请使用绝对路径。(此处:(Platform.isWindows()?"msvcrt":"c")指本地动态库msvcrt.dll)
                        CLibrary INSTANCE = (CLibrary) Native.loadLibrary(("/usr/lib/libtest.so"),
                        CLibrary.class);
                        
                // 声明将要调用的so中的方法,可以是多个方法(此处示例调用so动态库libtest.so中的Test01()方法)
                        void Test01(String str, int num);
                        
               
            }
    1 public static void main(String[] args) {
    2         String cou = CLibrary.INSTANCE.Test01("hi",123);
    3         System.out.println(cou);
    4 
    5     }

    3.又是调用so文件返回值是字符串的时候会出现乱码(解决方法如下)

    通过用Pointer来获取返回值,而so链接库的返回值要存到指针里面

    Java代码:

    public interface CLibrary extends Library {
               
                // DLL文件默认路径为项目根目录,若DLL文件存放在项目外,请使用绝对路径。(此处:(Platform.isWindows()?"msvcrt":"c")指本地动态库msvcrt.dll)
                        CLibrary INSTANCE = (CLibrary) Native.loadLibrary(("/usr/lib/libtest.so"),
                        CLibrary.class);
                        
                // 声明将要调用的so中的方法,可以是多个方法(此处示例调用so动态库libtest.so中的Test01()方法)
                        void Test01(String str, int num,Pointer p);
                        
               
            }
     public static void main(String[] args) {
            
             Pointer p = new Memory(22);
             CLibrary.INSTANCE.Test01("hi", 123, p);
             
             for(int i=0, sumi=21; i< sumi; i++){
                 
                 System.out.print((char) p.getByteArray(0, 21)[i]);
                 
                         }
        }

    so链接库方法声明方式:

    extern "C" void Test01(char* str, unsigned int num, char* strReturn){
    *******************************
    *****************
    **********
    return *****;
    }

    获取更多资源请访问:http://www.itcsdr.com/  或者请扫描右上角关注公众号:IT资源分享平台

  • 相关阅读:
    maven 多环境打包
    velocity 将数字转为以万为单位,保留2位小数
    mybatic 结果为null,返回0
    websocket-spring 整合
    烂泥:rsync配置文件详解
    烂泥:【转】rsync命令参数详解
    烂泥:linux文件同步之rsync学习(一)
    烂泥:使用snmpwalk采集设备的OID信息
    烂泥:apache密码生成工具htpasswd的应用
    烂泥:apache性能测试工具ab的应用
  • 原文地址:https://www.cnblogs.com/alex96/p/11363424.html
Copyright © 2011-2022 走看看