What is the Kotlin equivalent of this JNA code?

I’m new to JNA, and am trying to use its interface method (not sure what the actual name for that mode is.) Here is an example of Java JNA code from their documentation:

package com.sun.jna.examples;

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

/** Simple example of JNA interface mapping and usage. */
public class HelloWorld {

    // This is the standard, stable way of mapping, which supports extensive
    // customization and mapping of Java to native types.

    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary)
            Native.load((Platform.isWindows() ? "msvcrt" : "c"),
                                CLibrary.class);

        void printf(String format, Object... args);
    }

    public static void main(String[] args) {
        CLibrary.INSTANCE.printf("Hello, World\n");
        for (int i=0;i < args.length;i++) {
            CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
        }
    }
}

I’m trying to do something similar in Kotlin:

import com.sun.jna.*

interface Waynav: Library {

  val INSTANCE: Waynav
    get() = Native.load("waynav", Waynav::class.java)

  fun perspective_new(): Pointer

  fun perspective_load(ptr: Pointer, key: String, path: String): Byte

  // fun perspective_set_latitude_and_longitude(ptr: Pointer, latitude: Double?, longitude: Double?)

  fun perspective_get_layers(ptr: Pointer, key: String): Array<String?>

  fun perspective_free(ptr: Pointer)

}

class Engine {

  companion object {

    @JvmStatic
    fun main(args: Array<String>) {
      println("Starting up")
      val waynav = Waynav.INSTANCE
...

Nothing I do lets me access INSTANCE, however. Is this possible? I’m not fluent enough with Java to understand how JNA gets away with calling methods and accessing fields on an interface without an instantiated class.

Also, I know there is a direct class mapping, and I made some headway using that, but it looks like it doesn’t support some return types I need. It worked in that I called into my library, but I need to be able to return arrays of strings and such.

Thanks.

Why do you need your main static in kotlin and singletone for lib?

   interface Waynav : Library {
        fun perspective_new(): Pointer
        fun perspective_load(ptr: Pointer, key: String, path: String): Byte
        fun perspective_get_layers(ptr: Pointer, key: String): Array<String?>
        fun perspective_free(ptr: Pointer)
   }

   fun main(args: Array<String>) {
       val lib = Native.load("waynav", Waynav::class.java)
       lib.perspective_new()
   } 

but if you insist you can

    interface Waynav: Library {
        companion object {
             val INSTANCE by lazy { Native.load("waynav", Waynav::class.java) }
        }
        // ...
    }

    fun main(args: Array<String>) {
        val lib = Waynav.INSTANCE
        lib.perspective_new()
    }

Lazy it better than get() for you. In your code you get a new instance every call of INSTANCE, lazy loads once. But if you need to use it exactly in one class you can just create exemplar, instead of pseudoinject it from singletone.

Perfect, thanks, I’ll give that a shot. I’m porting this from a JNI
interface that had cleaner code, so my top priority was just proving
that I could call into this library via JNA before cleaning up the code.
This approach looks better, so I’ll try it out and report back.

Yup, this worked. Thanks a bunch!