Я пытаюсь сопоставить kstat library в Solaris 11.3 с Java, используя JNA. В то время как мне удалось заставить большинство структур работать, я провел последние 24 часа, сражаясь с особенно сложным объединением в рамках структуры внутри профсоюза.Сопоставление структуры внутри объединения в JNA
Я успешно получаю указатель на структуру kstat_named
Мне нужно использовать kstat_data_lookup(). Мой код правильно извлекает большую часть данных (имя, DATA_TYPE и без STRUCT членов союза) в этой C структуру:
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;
Я отображенная это в ЮНЕ следующим образом:
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" });
}
}
Этот код работает корректно для типов int32 (KSTAT_DATA_INT32). Однако, когда типом данных является KSTAT_DATA_STRING, что соответствует структуре str
внутри union
, я не уверен в правильном извлечении данных.
Я сопоставляются вложенную структуру, как это:
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" });
}
}
В конце концов я пытаюсь повторить поведение этого C макрос:
#define KSTAT_NAMED_STR_PTR(knptr) ((knptr)->value.str.addr.ptr)
Я пробовал несколько различных методов пытаются чтобы получить доступ к вышеуказанной структуре, но он, кажется, не читает правильные данные (значение len
находится в миллионах, и попытка прочитать строку ptr
вызывает segfault). Я пробовал:
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
Я также попытался:
- Указания
KstatNamedString
как тип вместоPointer
типа - Используя различные комбинации
ByReference
в обеих структурах и профсоюзы
Я повсюду гугл, включая попытку того, что, по моему мнению, было многообещающим результатом here, но ничего не работает.
Уверен, что я пропустил что-то простое.
Спасибо! 'super (p)' сделал трюк. –