Ich versuche, die kstat library in Solaris 11.3 zu Java mit JNA zuordnen. Während ich es geschafft habe, dass die meisten Strukturen funktionieren, habe ich die letzten 24 Stunden damit verbracht, mit einer besonders schwierigen Gewerkschaft innerhalb einer Struktur innerhalb einer Gewerkschaft zu kämpfen.Mapping einer Struktur in einer Union in JNA
Ich bin erfolgreich abrufen einen Zeiger auf eine kstat_named
Struktur, die ich brauche kstat_data_lookup(). Mein Code richtig ruft die meisten Daten (Name, data_type und Nicht-struct Mitglieder der Vereinigung) in dieser C-Struktur:
typedef struct kstat_named {
char name[KSTAT_STRLEN]; /* name of counter */
uchar_t data_type; /* data type */
union {
charc[16]; /* enough for 128-bit ints */
struct {
union {
char *ptr; /* NULL-terminated string */
} addr;
uint32_t len; /* length of string */
} str;
int32_t i32;
uint32_t ui32;
int64_t i64;
uint64_t ui64;
/* These structure members are obsolete */
int32_t l;
uint32_t ul;
int64_t ll;
uint64_t ull;
} value; /* value of counter */
} kstat_named_t;
ich dies in JNA zugeordnet haben, wie folgt:
class KstatNamed extends Structure {
public static class UNION extends Union {
public byte[] charc = new byte[16]; // enough for 128-bit ints
public Pointer str; // KstatNamedString
public int i32;
public int ui32;
public long i64;
public long ui64;
}
public byte[] name = new byte[KSTAT_STRLEN]; // name of counter
public byte data_type; // data type
public UNION value; // value of counter
public KstatNamed() {
super();
}
public KstatNamed(Pointer p) {
super();
this.useMemory(p);
this.read();
}
@Override
public void read() {
super.read();
switch (data_type) {
case KSTAT_DATA_CHAR:
value.setType(byte[].class);
break;
case KSTAT_DATA_STRING:
value.setType(Pointer.class);
break;
case KSTAT_DATA_INT32:
case KSTAT_DATA_UINT32:
value.setType(int.class);
break;
case KSTAT_DATA_INT64:
case KSTAT_DATA_UINT64:
value.setType(long.class);
break;
default:
break;
}
value.read();
}
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "name", "data_type", "value" });
}
}
Dieser Code funktioniert ordnungsgemäß für Int32-Typen (KSTAT_DATA_INT32). Wenn der Datentyp jedoch KSTAT_DATA_STRING ist, was der Struktur str
in union
entspricht, habe ich keinen Erfolg beim ordnungsgemäßen Abrufen der Daten.
Ich habe die verschachtelte Struktur wie folgt abgebildet:
class KstatNamedString extends Structure {
public static class UNION extends Union {
public Pointer ptr; // NULL-terminated string
}
public UNION addr;
public int len; // length of string
public KstatNamedString() {
super();
}
public KstatNamedString(Pointer p) {
super();
this.useMemory(p);
this.read();
}
@Override
public void read() {
super.read();
addr.setType(Pointer.class);
addr.read();
}
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "addr", "len" });
}
}
Letztlich Ich versuche, das Verhalten dieses C Makro zu replizieren: Der Versuch, mehrere verschiedene Methoden der
#define KSTAT_NAMED_STR_PTR(knptr) ((knptr)->value.str.addr.ptr)
Ich habe versucht, Zugriff auf die obige Struktur, aber es scheint nie die richtigen Daten zu lesen (der len
Wert ist in den Millionen und versucht, die Zeichenfolge ptr
zu lesen, verursacht Segfault). Ich habe versucht:
Pointer p = LibKstat.INSTANCE.kstat_data_lookup(ksp, name);
KstatNamed data = new KstatNamed(p);
KstatNamedString str = new KstatNamedString(data.value.str);
return str.addr.ptr.getString(0); // <--- Segfault on C side
Ich habe auch versucht:
- Angabe
KstatNamedString
als Typ anstelle desPointer
Typ - Mit verschiedenen Kombinationen von
ByReference
sowohl in den Strukturen und den Gewerkschaften
Ich habe überall gegooglet, einschließlich zu versuchen, was ich für ein vielversprechendes Ergebnis hielt here, aber nichts scheint zu funktionieren.
Ich bin sicher, ich vermisse etwas Einfaches.
Danke! 'super (p)' hat es geschafft. –