Search code examples
javac++scalajava-native-interfacejna

Structure JNA returns wrong value


From C++ code I am getting the structure.But all the values I am getting is default value.Below is my c++ code

extern "C" 
{ 
PDFCONTENTDATA GetPDFContentData(LPTSTR lptszS3FileURL)
{
PDFCONTENTDATA pdfContentData;
pdfContentData.m_uiRasterDPI = 100;

return pdfContentData;
}
}; 

Below is my java/scala code

@Structure.FieldOrder({ "m_uiRasterDPI"})
public class tagPDFContentData extends Structure {

    public static class ByValue extends tagPDFContentData implements Structure.ByValue { }
    public static class ByReference extends tagPDFContentData implements Structure.ByReference { }
    public volatile int m_uiRasterDPI;
}


trait CDocuLinkCoreServices extends Library{
  def GetPDFContentData(value: Pointer):  tagPDFContentData.ByValue
}

But I am getting

m_uiRasterDPI= 0

where it should return 100.


Solution

  • Here you go: https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo057

    To make a smooth call to JNA, there is a Java class recipeNo057.Data. This class is super simple

    package recipeNo057;
    
    import com.sun.jna.Library;
    import com.sun.jna.WString;
    import com.sun.jna.Native;
    import com.sun.jna.Structure;
    
    @Structure.FieldOrder({ "field" })
    public class Data extends Structure {
    
        public static class ByValue extends Data implements Structure.ByValue { }
        public static class ByReference extends Data implements Structure.ByReference { }
        public volatile int field;
    
    }
    

    on the other side (C++ side) we have "the same" structure.

    typedef struct data {
      int field;
    } 
    

    Scala binds all that stuff together by "linking" Java based class, JNA based call to native code, and native code in C++ itself.

    trait HelloWorld extends Library {
    
      def GetData(m: WString) : Data.ByValue;
    
    }
    
    object HelloJNA {
    
      def main(args:Array[String]):Unit = {
    
        val libc   = Native.load( "HelloWorld", classOf[HelloWorld] )
    
        var result = libc.GetData( new WString("I am passing String!") )
        println("Result: " + result.field);
    
      }
    }
    

    Note

    It's important to pay attention to type match between Java structures and C++ structures.