java - 在使用 Gradle 构建的 Java 代码中使用 C++ 代码的正确方法是什么?

标签 java android gradle makefile build.gradle

我一直致力于将 Android native Java 代码库移植到使用 grade 构建的纯 Java 应用程序。

Android 代码的build.gradle 文件使用C++ 代码,此依赖已声明如下。

android {
    
    ...

    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
        }
    }
}

对于使用 Gradle 生成的 java 应用程序执行此操作的正确方法是什么(我遵循了 this 教程)

到目前为止,这是我的 build.grade 文件的样子。

plugins {
    id 'java'
    id 'application'
}

repositories {
    jcenter()
}

dependencies {
    implementation 'com.google.guava:guava:28.0-jre'
    testImplementation 'junit:junit:4.12'
    implementation 'org.greenrobot:eventbus:3.1.1'
    
}

application {
    mainClassName = 'demo.App'
}

我用的是java 8,gradle版本是5.6.2,openjdk版本是1.8.0_222

编辑:环顾四周后,我知道可以使用 JNI 在 java 中使用 C++。

但是在android studio 中,android 项目可以在创建时配置为使用C++。此外,该项目使用了一个 makefile,不确定如何使用 JNI 完成

最佳答案

终于让它工作了,下面是它的工作原理,假设我想从 java 执行 System.loadLibrary("nativeCpp")

第 1 步:

将所有 C++ 代码移动到 src/nativeCpp/cpp/ 并删除 CMAKE.txt 文件。

第 2 步: 确保 build.gradle 看起来像这样:

plugins {
    id 'java'
    id 'application'
    id 'cpp'
}

repositories {
    jcenter()
}

dependencies {
    implementation 'com.google.guava:guava:28.0-jre'
    testImplementation 'junit:junit:4.12'        
}

application {
    mainClassName = 'demo.App'
}
run {
    systemProperty "java.library.path", file("${buildDir}/libs/nativeCpp/shared").absolutePath
}
model {
    platforms {
        x64 {
            architecture "x64"
        }
    }

    components {
        nativeCpp(NativeLibrarySpec) {


            binaries.all {
                cppCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
                cppCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/linux"
                cppCompiler.args '-fPIC'
            }

        }
    }
}

run.dependsOn  'nativeCppSharedLibrary'

说明:Gradle 要求您将所有 native 组件及其名称保存在 src 目录中,它指的是这个目录(在我的例子中是 src/nativeApp)来构建您的 native 代码。

当您使用 gradle run 执行运行任务时,您想要传递给语言编译器(在本例中为 Java)的任何特殊指令都是从 build.gradle 中的运行属性中选取的。我想传递 java.library.path 以确保 java 可以读取它,没有它你会在构建过程中得到 java.lang.UnsatisfiedLinkError

接下来,我们定义模型 block 中的组件以及如何构建它们,binaries.all 属性中的指令在命令行中转换为:

gcc -I /usr/lib/jvm/java-1.8.0-openjdk-amd64/include -I /usr/lib/jvm/java-1.8.0-openjdk-amd64/include/linux -shared -o librendering.so native.cpp -fPIC

我们指定 -I 选项来告诉 gcc 编译器 JNI 在我们系统上的位置。此路径可能因您而异。

这将编译您的 C++ 代码并将其存储在 /libs/nativeCpp/shared 中,run 可以找到它

关于java - 在使用 Gradle 构建的 Java 代码中使用 C++ 代码的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59344184/

相关文章:

java - 如何让 Eclipse 使用 Gradle 生成 MapStruct Mappers

java - 这是一个堆栈吗?

java - Hibernate 模板关闭事务

java - RXJava。可观察的连续人口

android - 窗口背景被状态栏剪裁

android - 在多模块项目中使用 Firebase

java - 在 Java 中添加引号

android - Xamarin - Visual Studio 卡在 zipalign.exe

android - 通过蓝牙从android浏览Raspberry Pi的文件系统

kotlin - 尝试在 gradle kotlindsl 中包含 swagger-codegen