Kotlin JVM JNI C++ Inheritance and Callback using SWIG

Submitted by Dickens A S on Tue, 07/20/2021 - 03:59

This Article demonstrates how to Inherit class from C++ class and how to make C++ calls back the Kolin function using overriding

In case there is Java or Kotlin inheritance is used how a JNI function get a handle for that.

System.loadLibrary is used to load the JNI library in JVM.

Below code explains how the inherited function is invoked and a callback which is written in Java or kotlin is invoked from a C++ code.

The Gradle SWIG Task of cpplib

val swigTask: Exec by tasks.creating(Exec::class) {
    commandLine (
        "swig",
        "-c++",
        "-java",
        "-cppext",
        "cpp",
        "-addextern",
        "-directors",
        "-module",
        "${project.name}",
        "src\\main\\swig\\${project.name}.i"
    )
}

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

class KotlinCallback : Callback {
    constructor(): super() {
        
    }
    override fun run()
    {
        println("From Kotlin KotlinCallback::run()");
    }
}

class App {
    fun demo() {
        var callback = KotlinCallback()
        var caller = Caller()
        caller.setCallback(callback)
        caller.call()
        caller.delCallback()
    }
        
    companion object {
        init {
            System.loadLibrary("cpplib")
        }
    }
}

fun main(args: Array<String>) {
    App().demo()
    
}

The C++ Code

/*
 * This C++ source file was generated by the Gradle 'init' task.
 */

#include <iostream>
#include <stdlib.h>
#include "cpplib.h"

void jniexample::Callback::run() {
    std::cout << "From C++ Callback::run()" << std::endl;
}

jniexample::Callback::~Callback() { 
    std::cout << "From C++ Callback::~Callback()" << std:: endl; 
}

jniexample::Caller::~Caller() {
    delCallback();
}

void jniexample::Caller::delCallback() { 
    delete _callback; 
    _callback = 0; 
}

void jniexample::Caller::setCallback(Callback *cb) { 
    delCallback(); 
    std::cout << "From C++ Setting callback" << std:: endl; 
    _callback = cb; 
}

void jniexample::Caller::call() { 
    if (_callback) { 
        _callback->run();
    } 
}

The SWIG Code

%{
#include "../public/cpplib.h"
%}

%include "../public/cpplib.h"

Output

> Task :run
From C++ Setting callback
From Kotlin KotlinCallback::run()
From C++ Callback::~Callback()

Here the C++ calls the kotlin function "run" through inheritance override

Source Code

Finished!

 

Add new comment