This Article demonstrates how to pass pointers and arrays in and out using pure C code and JNI and force pure C code in Gradle
The Gradle SWIG Task of cpplib
val swigTask: Exec by tasks.creating(Exec::class) {
commandLine (
"swig",
"-java",
"-cppext",
"c",
"-addextern",
"-module",
"${project.name}",
"src\\main\\swig\\${project.name}.i"
)
}
The Gradle C Compiler Arguments (-lc -x c -std=gnu99) forces the g++ to use gcc compiler as pure C compiler
tasks.withType(CppCompile::class.java).configureEach {
dependsOn(swigTask)
doFirst {
copy {
from("${project.rootDir}/${project.name}/src/main/swig") {
rename("${project.name}_wrap.c", "${project.name}_wrap.cpp")
}
into("${project.rootDir}/${project.name}/src/main/cpp")
exclude("*.java")
exclude("*.i")
}
}
compilerArgs.addAll(toolChain.map { toolChain ->
when (toolChain) {
is Gcc, is Clang -> listOf(
"-c",
"-v",
"-x",
"c",
"-fpic",
"-std=gnu99",
"-Wall",
"-Werror",
"-Wno-unused",
"-nodefaultlibs",
"-lc",
"-g",
"-I/usr/java/include",
"-I$javaHome/include",
"-I$javaHome/include/win32"
)
else -> listOf()
}
})
}
Gradle C Linker Arguments
tasks.withType(LinkSharedLibrary::class.java).configureEach {
linkerArgs.addAll(toolChain.map { toolChain ->
when (toolChain) {
is Gcc, is Clang -> listOf(
"-v",
"-g",
"-Wl,--out-implib=${project.name}.dll.a",
"-Wl,--export-all-symbols",
"-Wl,--enable-auto-import",
"-Wl,--output-def=${project.name}.def"
)
else -> listOf()
}
})
doLast {
copy {
from("${project.rootDir}/${project.name}/build/lib/main/debug")
into("${project.rootDir}")
exclude("*.java")
exclude("*.i")
exclude("*.obj")
}
copy {
from("${project.rootDir}/${project.name}/src/main/swig")
into("${project.rootDir}/src/main/java")
exclude("*.i")
exclude("*.cpp")
exclude("*.c")
}
copy {
from("${project.rootDir}/${project.name}/${project.name}.dll.a")
into("${project.rootDir}")
}
copy {
from("${project.rootDir}/${project.name}/${project.name}.def")
into("${project.rootDir}")
}
}
}
this code is written generic based on the folder name of the sub project is assumed as the DLL file name
These gradle tasks plays the important role, otherwise you need to manually copy the files
The Kotlin Code
import cpplibJNI.*
class App {
fun demo() {
//Example 1
var a = new_intp()
var b = new_intp()
var c = new_intp()
intp_assign(a,37)
intp_assign(b,42)
println("calling C add function")
add(a,b,c)
var res = intp_value(c)
println("printing result")
println("37 + 42 = " + res)
//Example 2
var a1 = new_doubleArray(10)
for( i in 0..10){
doubleArray_setitem(a1, i, 2.0 * i)
}
print_array(a1)
delete_doubleArray(a1)
//Example 3
var x1 = new_doubleArray(10)
for( i in 0..10){
doubleArray_setitem(x1, i, 2.0 * i)
}
modify_array(x1)
print_array(x1)
delete_doubleArray(x1)
//Example 4
var x2 = new_doubleArray(10)
var y2 = new_doubleArray(10)
for( i in 0..10){
doubleArray_setitem(x2, i, 2.0 * i)
}
copy_array(x2, y2)
print_array(y2)
delete_doubleArray(x2)
delete_doubleArray(y2)
}
companion object {
init {
System.loadLibrary("cpplib")
}
}
}
fun main(args: Array<String>) {
var result = App().demo();
}
The C code (but stored as .cpp)
#include "cpplib.h"
#include <stdlib.h>
#include <stdio.h>
void add(int *x, int *y, int *result) {
*result = *x + *y;
}
void print_array(double x[10]) {
printf("\nprint_array\n");
int i;
for (i = 0; i < 10; i++) {
printf("[%d] = %g\n", i, x[i]);
}
}
void modify_array(double x[10]) {
printf("\nmodify_array\n");
int i;
for (i = 0; i < 10; i++) {
x[i] = x[i] * 3.0;
}
}
void copy_array(double x[10], double y[10]) {
printf("\ncopy_array\n");
int i;
for (i = 0; i < 10; i++) {
y[i] = x[i];
}
}
The SWIG Code
%include "cpointer.i"
%include "carrays.i"
%pointer_functions(int, intp);
%array_functions(double, doubleArray);
%{
#include "../public/cpplib.h"
%}
%include "../public/cpplib.h"
Final Output
> Task :run
calling C add function
printing result
37 + 42 = 79
print_array
[0] = 0
[1] = 2
[2] = 4
[3] = 6
[4] = 8
[5] = 10
[6] = 12
[7] = 14
[8] = 16
[9] = 18
modify_array
print_array
[0] = 0
[1] = 6
[2] = 12
[3] = 18
[4] = 24
[5] = 30
[6] = 36
[7] = 42
[8] = 48
[9] = 54
copy_array
print_array
[0] = 0
[1] = 2
[2] = 4
[3] = 6
[4] = 8
[5] = 10
[6] = 12
[7] = 14
[8] = 16
[9] = 18
Finished!