Solaris 11.3의 kstat library을 JNA를 사용하여 Java로 매핑하려고합니다. 필자는 구조의 대부분을 작동시킬 수 있었지만 지난 24 시간 동안 특히 어려운 노동 조합 내에서 노조와 싸우는 데 보냈습니다.JNA의 공용 구조체 내 구조체 매핑
kstat_data_lookup()을 사용하여 필요한 kstat_named
구조에 대한 포인터를 성공적으로 검색하고 있습니다. 내가 JNA이를 매핑 한
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" });
}
}
내 코드가 제대로이 C 구조의 데이터 (이름, DATA_TYPE, 그리고 노동 조합의 비 구조체 명)의 대부분은 검색 이 코드는 int32 형식 (KSTAT_DATA_INT32)에서 올바르게 작동합니다. 그러나 union
내부의 str
구조에 해당하는 데이터 형식이 KSTAT_DATA_STRING 인 경우 데이터를 올바르게 검색하는 데 아무런 문제가 없습니다.
나는 다음과 같이 중첩 된 구조를 매핑 한 :
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
가 나는 또한 시도했다 :
- 대신 구조 모두에서
ByReference
의 다양한 조합을 사용하여Pointer
유형 - 의 종류와 조합 로
KstatNamedString
지정
저는 유망한 결과라고 생각하는 것을 포함하여 어디에서나 봤습니다. here,하지만 아무것도 작동하는 것 같습니다.
나는 뭔가 간단하다고 생각합니다.
고마워요! 'super (p)'가 트릭을했습니다. –