Using python's ctypes, it's possible to specify a pointer that takes a type:
class METADATA(Structure):
_fields_ = [("classes", c_int),
("names", POINTER(c_char_p))]
With JNR, it looks like this:
public static class Metadata extends Struct{
public Metadata(jnr.ffi.Runtime rt) {
super(rt);
}
public final Struct.Unsigned32 classes = new Struct.Unsigned32();
public final Struct.Pointer names = new Struct.Pointer();
}
However, is it possible to type the names
field as a Pointer to a String?
I'm not familiar with python's ctypes but assuming the type of names
is either char*
or char**
you could try to use one of the following approaches.
For a shared library,
#include <stdlib.h>
#include <stdio.h>
struct MyStruct {
int classes;
char *names;
char **names2;
};
struct MyStruct *get_my_struct() {
struct MyStruct *my_struct = malloc(sizeof(struct MyStruct));
my_struct->classes = 42;
my_struct->names = "My Names";
char **names2 = calloc(2, sizeof(char *));
names2[0] = "Stack";
names2[1] = "Overflow";
my_struct->names2 = names2;
return my_struct;
}
The struct can be defined as follows
public static class MyStruct extends Struct {
public MyStruct(Runtime runtime) {
super(runtime);
}
public final Struct.Signed32 classes = new Struct.Signed32();
// For char* the support is built-in
public final Struct.String names = new Struct.UTF8StringRef();
// For char** you could wrap a pointer and override getStringMemory
public final UTF8StringRef[] names2 = UTF8StringRefArray(new Struct.Pointer(), 2);
protected UTF8StringRef[] UTF8StringRefArray(Pointer pointer, int stringLength) {
UTF8StringRef[] array = new UTF8StringRef[stringLength];
for (int i = 0; i < array.length; i++) {
int index = i;
array[i] = new UTF8StringRef() {
@Override
protected jnr.ffi.Pointer getStringMemory() {
return pointer.get().getPointer(getRuntime().addressSize() * index);
}
};
}
return array;
}
}
For the above, the following code will print 42 My Names are Stack, Overflow
.
public interface MyLib {
MyStruct get_my_struct();
}
public static void main(String[] args) {
MyLib mylib = LibraryLoader.create(MyLib.class).load("mylib.so");
MyStruct myStruct = mylib.get_my_struct();
System.out.printf("%d %s are %s, %s", myStruct.classes.get(), myStruct.names.get(),
myStruct.names2[0].get(), myStruct.names2[1].get());
}