CrabBeach
CrabBeach

Reputation: 21

How to use this method in Java by JNA?

I am trying to make a connection between a c++ dll and my java project by JNA. The dll.h is in this gitHub: dll.h.

EXTERN_C DLLEXPORT int STDCALL SolveBoard(
  struct deal dl,
  int target,
  int solutions,
  int mode,
  struct futureTricks * futp,
  int threadIndex);
struct deal
{
  int trump;
  int first;
  int currentTrickSuit[3];
  int currentTrickRank[3];
  unsigned int remainCards[DDS_HANDS][DDS_SUITS];
};
struct futureTricks
{
  int nodes;
  int cards;
  int suit[13];
  int rank[13];
  int equals[13];
  int score[13];
};

I am fresh to JNA and c++, I have tried to code in Java like this:

public interface DllAl extends StdCallLibrary{
DllAl instanceDll = (DllAl)Native.loadLibrary("dds",DllAl.class);
public int SolveBoard(deal deal,int target,int solutions,int mode, futureTricks fut,int threadIndex);
public int PrintFut(char title[],futureTricks fut);

public static class deal extends Structure{
      public int trump;
      public int first;
      public int currentTrickSuit[] = new int [3];
      public int currentTrickRank[] = new int [3];
      public int remainCards[][] = new int[4][4];
      public static class ByReference extends deal implements Structure.ByReference {}  
      public static class ByValue extends deal implements Structure.ByValue {}
        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList(new String[]{"trump", "first", "currentTrickSuit", "currentTrickRank","remainCards"});  
        }  

}
public static class futureTricks extends Structure{
    public int nodes;
    public int cards;
    public int suit[] = new int [13];
    public int rank[] = new int [13];
    public int equals[] = new int[13];
    public int score[] = new int[13];
      public static class ByReference extends futureTricks implements Structure.ByReference {}  
      public static class ByValue extends futureTricks implements Structure.ByValue {}
        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList(new String[]{"nodes", "cards", "suit", "rank","equals","score"});  
        }  

}

} However, it returns mistakes:

Exception in thread "main" java.lang.NullPointerException
at java.lang.reflect.Array.getLength(Native Method)
at com.sun.jna.Native.getNativeSize(Native.java:1162)
at com.sun.jna.Structure.getNativeAlignment(Structure.java:1360)
at com.sun.jna.Structure.getNativeAlignment(Structure.java:1385)
at com.sun.jna.Structure.deriveLayout(Structure.java:1221)
at com.sun.jna.Structure.calculateSize(Structure.java:1053)
at com.sun.jna.Structure.allocateMemory(Structure.java:380)
at com.sun.jna.Structure.ensureAllocated(Structure.java:356)
at com.sun.jna.Structure.ensureAllocated(Structure.java:346)
at com.sun.jna.Structure.write(Structure.java:737)
at com.sun.jna.Structure.autoWrite(Structure.java:2047)
at com.sun.jna.Function.convertArgument(Function.java:512)
at com.sun.jna.Function.invoke(Function.java:305)
at com.sun.jna.Library$Handler.invoke(Library.java:236)
at com.sun.proxy.$Proxy0.SolveBoard(Unknown Source)
at DllAl.main(DllAl.java:98)

Upvotes: 1

Views: 384

Answers (1)

Daniel Widdis
Daniel Widdis

Reputation: 9091

JNA does not map 2D (or 3D, 4D, etc.) arrays. If you need to map a 2D array you should replace it with a 1D array and then write your own code to translate.

You need to change this line:

public int remainCards[][] = new int[4][4];

to:

public int remainCards[] = new int[16];

Then add a method which translates the 2D coordinates (e.g., hands, suits) to the 1D index (e.g., 4*hands + suits).

Upvotes: 1

Related Questions