基于中间接口库,实现Java使用JNA调用C++ so动态库/c调用C++ so动态库/Java C++混合编程(详细步骤)

因业务需要,需使用Java调用C++ so动态库,研究了几天,调试通了,发现现有资料比较零散,本文做个汇总。

一。C++生成so动态库

//cplus.cpp
#include<stdio.h>
#include<iostream>
int addCplus(int x, int y) {
    printf("add by C++\n");
    std::cout << "generate a c++ library" << std::endl;
    return x + y;
}

编译

g++ -m64 -fPIC --shared -o libcplus.so cplus.cpp

移动编译好的so动态库到/usr/lib 用户库目录下,便于其他程序调用

sudo cp libcplus.so /usr/lib/

 关于linux下libxxx.so动态库位置
建议放到/usr/lib目录下,执行命令ldconfig重新加载动态库即可。

sudo ldconfig

二。 中间接口库生成so动态库

//mid.cpp
#include "iostream"
int addCplus(int a, int b);
#ifdef __cplusplus
extern "C" {
#endif
int m_addCplus(int x, int y)
{
    return addCplus(x, y);
}
#ifdef __cplusplus
}
#endif

编译,其中-l cplus 来自于libcplus.so动态库文件名

g++ -m64 -fPIC --shared -o libmid.so mid.cpp -l cplus

移动编译好的so动态库到/usr/lib用户库目录下,便于其他程序调用

sudo cp libmid.so /usr/lib/ 

三。C 调用C++

//test.c
#include <stdio.h>

int main()
{
    int res=m_addCplus(3,5);
    printf("res=%d\n",res);
    return 0;
}

编译,其中-l mid 来自于libmid.so动态库文件名

gcc test.c -l mid -o test

运行

 » ./test
add by C++
generate a c++ library

res=8

gcc test.c -lmid -o test -L./
//大L指定路径,小l指定库名,这种使用方法,有时会显示找不到库,需要配置库路径环境变量
//export LD_LIBRARY_PATH="data/chenxiaohui/SIFT3D-1.4.6-Linux/usr/local/lib/sift3d:$LD_LIBRARY_PATH"
或者gcc test.c -o test /usr/lib/libmid.so
//直接路径+名字
注意事项:如果在板子上运行的话,可以用export LD_LIBRARY_PATH声明库的路径比如mount,nfs在/mnt,把库放到/mnt里面然后export LD_LIBRARY_PATH="/mnt:$LD_LIBRARY_PATH"就可以让程序找到了

 四。Java调用C++

pom.xml引入maven

        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>jna</artifactId>
            <version>5.13.0</version>
        </dependency>
        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>platform</artifactId>
            <version>3.5.2</version>
        </dependency>

1.类直接调用so动态库

package com.xx.xx;

import com.sun.jna.Native;

/**
 * Demo1.java
 *
 * @author :qiyu
 * @version :1.0
 * @description: 类中直接调用so动态库
 * @date :2023/6/26 上午9:09
 */
public class Demo1 {
    static {
        Native.register("libmid.so");
    }

    public static native int m_addCplus(int x, int y);


    public static void main(String[] args) {
        System.out.println("java.library.path:" + System.getProperty("java.library.path"));
        System.out.println("***************************");
        System.out.println(m_addCplus(1, 2));
        System.out.println("***************************");
    }
}

 运行结果

java.library.path:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
***************************
add by C++
generate a c++ library
3
***************************

2.接口实现,便于复用

接口

package com.xx.xx;

import com.sun.jna.Library;
import com.sun.jna.Native;

/**
 * MySo.java
 * @author :qiyu
 * @version :1.0
 * @description: 接口调用so动态库,便于其他类调用
 * @date :2023/6/26 上午10:34
 */
public interface MySo extends Library {
    MySo myso = (MySo) Native.load("libmid.so", MySo.class);

    int m_addCplus(int x, int y);
}

类调用接口

package com.xx.xx;

import java.io.IOException;

/**
 * Main.java
 *
 * @author :qiyu
 * @version :1.0
 * @description:调用接口
 * @date :2023/6/26 上午10:35
 */
public class Main {
    public static void main(String[] args) throws IOException {
        System.out.println("java.library.path:" + System.getProperty("java.library.path"));
//        System.out.println("是Linux平台?=" + Platform.isLinux());
        int value = MySo.myso.m_addCplus(1, 1);
        System.out.println("value=" + value);
    }
}

运行类Main方法

java.library.path:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
add by C++
generate a c++ library
value=2 

五。Java/C/C++数据类型映射

JNA实战系列:JNA与C语言中的数据类型映射以及复杂结构体传参示例_jna 类型映射_wangzhongyudie的博客-CSDN博客

参考:

C代码调用C++编译的so库_c调用c++ so_I&You的博客-CSDN博客

IDEA 搭建简单的 JNA 开发环境_哔哩哔哩_bilibili

Java使用JNA调用C/C++动态链接库dll_哔哩哔哩_bilibili

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用JNA调用C++的构造函数需要一些额外的步骤。首先,需要在C++中编写一个导出构造函数的动态。然后,在Java使用JNA加载该动态调用该构造函数。下面是一个简单的示例: 首先,创建一个C++的动态,例如libexample.so。在该中,定义一个类Example,如下所示: ```cpp class Example { public: Example(int a, int b); int add(); private: int m_a; int m_b; }; Example::Example(int a, int b) : m_a(a), m_b(b) {} int Example::add() { return m_a + m_b; } ``` 然后,为该类定义一个构造函数的导出函数,如下所示: ```cpp extern "C" { Example* Example_new(int a, int b) { return new Example(a, b); } } ``` 编译并生成动态,例如libexample.so。 接下来,在Java使用JNA加载该动态调用该构造函数,如下所示: ```java import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.ptr.PointerByReference; public class ExampleJNA { public interface ExampleLibrary extends Library { ExampleLibrary INSTANCE = (ExampleLibrary) Native.loadLibrary("example", ExampleLibrary.class); Pointer Example_new(int a, int b); } public static void main(String[] args) { Pointer examplePtr = ExampleLibrary.INSTANCE.Example_new(1, 2); Example example = new Example(examplePtr); System.out.println(example.add()); // 输出 3 } public static class Example { private Pointer examplePtr; public Example(Pointer examplePtr) { this.examplePtr = examplePtr; } public int add() { return examplePtr.getInt(0) + examplePtr.getInt(4); } } } ``` 在Java中,使用JNA的Pointer类来表示C++对象的指针。在Java中创建Example对象时,需要将C++对象的指针传递给Example类的构造函数。在Example类中,使用Pointer类来访问C++对象的成员变量和成员函数。 注意:为了使用JNA调用C++的构造函数,需要使用extern "C"来告诉编译器该函数的名称应该是C链接方式的。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值