Search code examples
javascalajava-native-interfacec++-clijna

Unable to access Memory reference with help of JNA library


I am trying to access this piece of c++ code through JNA library that is written in .dll file

bool Services::ReverseString(const std::wstring &strIn)
{

    return true;
} 

My scala code is written below

trait CoreServices extends Library{

  def ReverseString(m:WString):Boolean

}
  val librarypath = "somepath"
    System.setProperty("jna.library.path", librarypath)
    val libc = Native.load("Services", classOf[CDocuLinkCoreServices])
    val x=libc.ReverseString(new WString("dddd"))

But I am getting the below error

java.lang.error invalid memory access

I am pretty new to JNA. ANy help will be appreciated.


Solution

  • I doubt you can call C++ code from Scala without using C style naming convention. I guess, the only way to go here is via extern "C" wrapper

    For the following project tree

    .
    |-- Makefile
    |-- c
    |   `-- Services.cc
    |-- jar
    |   `-- jna-5.4.0.jar
    |-- lib
    |   |-- libServices.dylib
    |   `-- libServices.dylib.dSYM
    |       `-- Contents
    |           |-- Info.plist
    |           `-- Resources
    |               `-- DWARF
    |                   `-- libServices.dylib
    `-- scala
    |   `-- jna_call.scala
    `-- target
    

    and following code

    Scala

    import com.sun.jna.Library
    import com.sun.jna.WString
    import com.sun.jna.Native
    
    trait Services extends Library {
    
      def ReverseStringWrapper(m:WString) : Boolean
    
    }
    
    object JNA {
      def main(args:Array[String]):Unit = {
        println("Testin JNA!! ")
        val librarypath = "./lib"
        System.setProperty("jna.library.path", librarypath)
        val libc = Native.load("Services", classOf[Services])
        val x=libc.ReverseStringWrapper(new WString("dddd"))
        println("Result: " + x);
      }
    }
    

    where native code looks like this

    C++

    #include <string>
    
    class Services {
      public:
        bool ReverseString(const std::wstring &strIn);
    };
    
    bool Services::ReverseString(const std::wstring &strIn)
    {
      return true;
    }
    
    extern "C" {
    
    bool ReverseStringWrapper(const std::wstring &strIn)
    {
      Services s;
      return s.ReverseString(strIn);
    }
    
    }
    

    and library being built following way

    > c++ -std=c++11 -g -shared \
      -fpic -I${JAVA_HOME}/include \
      -I${JAVA_HOME}/include/$(ARCH) \
      c/Services.cc -o lib/libServices.dylib
    

    while Scala code is compiled following way

    > scalac -d target -classpath "jar/jna-5.4.0.jar" scala/jna_call.scala
    

    and executed this way

    > scala -classpath "./target:jar/jna-5.4.0.jar" JNA
    Testin JNA!!
    Result: true
    

    everything works as expected.

    You can find full sample code here: https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo054