Search code examples
javac++java-native-interfacejna

Using JNA to access a struct containing a vector<char*>


I have a C++ library that uses a struct which contains a vector. I am having some difficulty determining the correct way to access this from Java via JNA.

My C++ structure:

#include <vector>

struct topic {
    char* src_id;
    char* dest_id;
    int32_t num;
    std::vector<char*> names;
};

My Java class:

public final class Topic extends Structure {

    public String src_id;
    public String dest_id;
    public int num;
    public String[] names; // This doesn't work

    public Topic() {

    }

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList(new String[] { "src_id", "dest_id", "num", "names" });
    }

}

Solution

  • This solution worked for me:

    package com.example;
    
    import java.util.Arrays;
    import java.util.List;
    
    import com.sun.jna.Library;
    import com.sun.jna.Native;
    import com.sun.jna.Pointer;
    import com.sun.jna.StringArray;
    import com.sun.jna.Structure;
    
    public class Example {
    
        public interface CLibrary extends Library {
    
            public static class Topic extends Structure {
                public static class ByReference extends Topic implements Structure.ByReference {
                }
    
                public String src_id;
                public String dest_id;
                public int num;
    
                public int numVals;
                public Pointer names; // char**
    
                @Override
                protected List<String> getFieldOrder() {
                    return Arrays.asList(new String[] { "src_id", "dest_id", "num", "numVals", "names" });
                }
            }
    
            public void sendTopic(Topic.ByReference pVal);
        }
    
        public static void main(String[] args) {
    
            final CLibrary clib = Native.loadLibrary("example.dll", CLibrary.class);
    
            final String[] myArray = new String[5];
            myArray[0] = "one";
            myArray[1] = "two";
            myArray[2] = "three";
            myArray[3] = "four";
            myArray[4] = "five";
    
            CLibrary.Topic.ByReference ref = new CLibrary.Topic.ByReference();
            ref.numVals = 5;
            ref.names = new StringArray(myArray);
    
            clib.sendTopic(ref);
        }
    }