Unknown Source Error in JNA ( Return Struct Array function in C)

442 views Asked by At

I try to make JNA application. However , I can not get sturct array from C. I get error in java side ( com.sun.Proxy.$Proxy0.fill(Unknown Source))

This is my part of c code below. I compiled as shared libary and I can use other functions. Just giving error when I call fill function .

typedef struct A{
    double Value;
    char Type; 
    char Name[100];
    char SymbolTableName[100];
    int updateMode;
    int dataType;
    char ulSize;
} A;

typedef struct B{
    int numAs;
    struct A* as;
} B;

B fill(void){   
    B sVal;
    sVal.numAs=100;
    int i=0;
    sVal.as = (A*)malloc(sizeof(A) * sVal.numAs);
    memset(sVal.as, 0, sizeof(A) * sVal.numAs);
    //X in scope , everything is ok here.
    X= ReadShared(); // It return struct array , X is struct same type.
    for(i=0; i<sVal.numAs; i++)
    {
        sVal.as[i].Value=X->datas[i].Value; 
        sVal.as[i].Type=X->datas[i].Type;
        strcpy(sVal.as[i].Name,X->datas[i].Name);
        strcpy(sVal.as[i].SymbolTableName,X->datas[i].SymbolTableName);
        sVal.as[i].updateMode=X->datas[i].updateMode;   
        sVal.as[i].dataType=X->datas[i].dataType;   
        sVal.as[i].ulSize=X->datas[i].ulSize;           
    }
    return sVal;

}

This is my Java Part below.

public class TestClass {

    public interface Test extends Library {

        public static class A extends Structure {
            public static class ByReference extends A implements Structure.ByReference{}
            double Value;
            char Type; 
            char Name;
            char SymbolTableName;
            int updateMode;
            int dataType;
            char ulSize;

            protected List getFieldOrder() {
                // TODO Auto-generated method stub
                return null;
            }
        }

        public static class B extends Structure {
            public static class ByValue extends B implements Structure.ByValue {}

            public int numAs;
            public A.ByReference as;
            protected List getFieldOrder() {
                // TODO Auto-generated method stub
                return null;
            }
        }

        public B.ByValue fill();
    }

    /**
     * @param args
     */
    public   TestClass(){

    }
    static void funcc(){
        NativeLibrary.addSearchPath("tester", "/root/Desktop/");//Path is true
        Test test=(Test)Native.loadLibrary("tester", Test.class);
        Test.B.ByValue jig=test.fill();

        Test.A[] Avals = (Test.A[])jig.as.toArray(jig.numAs);
    }
}

How will I correct this error ? Why it happens? Maybe there is something missing what ı can not see( Java side or c side ). Thanks for any helps.

at com.sun.jna.Structure.getFields(Structure.java:911) at com.sun.jna.Structure.deriveLayout(Structure.java:1058) at com.sun.jna.Structure.calculateSize(Structure.java:982) at com.sun.jna.Structure.calculateSize(Structure.java:949) at com.sun.jna.Structure.allocateMemory(Structure.java:375) at com.sun.jna.Structure.(Structure.java:184) at com.sun.jna.Structure.(Structure.java:172) at com.sun.jna.Structure.(Structure.java:159) at com.sun.jna.Structure.(Structure.java:151) at MyTest.TestClass$Test$B.(TestClass.java:38) at MyTest.TestClass$Test$B$ByValue.(TestClass.java:39) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:526) at java.lang.Class.newInstance(Class.java:379) at com.sun.jna.Structure.newInstance(Structure.java:1651) at com.sun.jna.Function.invoke(Function.java:408) at com.sun.jna.Function.invoke(Function.java:315) at com.sun.jna.Library$Handler.invoke(Library.java:212) at com.sun.proxy.$Proxy0.fill(Unknown Source) at MyTest.TestClass.funcc(TestClass.java:63) at MyTest.t7500.doGet(t7500.java:51) at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745)

1

There are 1 answers

0
technomage On

You haven't defined the order of structure fields within your Structure classes. JNA needs this information in order to properly read and write from native memory.

You have also incorrectly mapped native char and char[].

For class A, you need this:

double Value;
byte Type; 
byte[] Name = new byte[100];
byte[] SymbolTableName = new byte[100];
int updateMode;
int dataType;
byte ulSize;

protected List getFieldOrder() {
    return Arrays.asList("Value", "Type", "Name", "SymbolTableName", "updateMode", "dataType", "ulSize");
}

For class B, you need this:

protected List getFieldOrder() {
    return Arrays.asList("numAs", "as");
}