Здравствуйте, StanislavK, Вы писали:
SK>Здравствуйте, Infernal, Вы писали:
I>>Вроде разобрался. Завтра если интересно, отпишусь по результатам. SK>Ну и где результаты?
Да, сорри.
Example.java
package test;
import org.graalvm.nativeimage.c.CContext;
import org.graalvm.nativeimage.c.function.CLibrary;
import org.graalvm.nativeimage.c.struct.CField;
import org.graalvm.nativeimage.c.struct.CFieldAddress;
import org.graalvm.nativeimage.c.struct.CPointerTo;
import org.graalvm.nativeimage.c.struct.CStruct;
import org.graalvm.word.Pointer;
import org.graalvm.word.PointerBase;
import java.util.Collections;
import java.util.List;
@CContext(Example.Headers.class)
@CLibrary("c")
public class Example {
public static class Headers implements CContext.Directives {
@Override
public List<String> getHeaderFiles() {
return Collections.singletonList("\"[path_to]/my_header.h\"");
}
}
@CPointerTo(MyUnion.class)
public interface MyUnionPtr extends PointerBase {
MyUnion read();
void write(MyUnion data);
}
/*
typedef union my_union
{
uint8_t bb;
uint16_t ww;
uint8_t arr[32];
} my_union;
*/
@CStruct("union my_union")
public interface MyUnion extends PointerBase {
@CField("bb")
byte getByte();
@CField("bb")
void setByte(byte b);
@CField("ww")
short getWord();
@CField("ww")
void setWord(short word);
@CFieldAddress("arr")
Pointer getArray();
}
/*
typedef struct my_struct
{
char cc;
int size;
union my_union *data ;
} my_struct;
*/
@CStruct("my_struct")
public interface MyStruct extends PointerBase {
@CField("cc")
byte getChar();
@CField("cc")
void setChar(byte b);
@CField("size")
int getSize();
@CField("size")
void setSize(int size);
@CFieldAddress("data")
MyUnionPtr getData();
}
}
ExampleIoctl.java
package test;
import org.graalvm.nativeimage.UnmanagedMemory;
import org.graalvm.nativeimage.c.CContext;
import org.graalvm.nativeimage.c.function.CFunction;
import org.graalvm.nativeimage.c.function.CLibrary;
import org.graalvm.nativeimage.c.struct.SizeOf;
import org.graalvm.word.PointerBase;
import java.util.Collections;
import java.util.List;
@CContext(ExampleIoctl.Headers.class)
@CLibrary("c")
public class ExampleIoctl {
public class Headers implements CContext.Directives {
public List<String> getHeaderFiles() {
return Collections.singletonList(
"\"/usr/include/linux/ioctl.h\""
);
}
}
private static class Delegate {
@CFunction(transition = CFunction.Transition.NO_TRANSITION)
public static native int ioctl(int fd, long command, PointerBase ptr);
}
public static void static void main(String[] args) {
Example.MyStruct struct = UnmanagedMemory.malloc(
SizeOf.get(Example.MyStruct.class)
);
Example.MyUnion union = UnmanagedMemory.malloc(
SizeOf.get(Example.MyUnion.class)
);
try {
// TODO fill values for struct/union
// Set ptr
struct.getData().write(union);
Delegate.ioctl([file_id], [command],struct);
} finally {
UnmanagedMemory.free(union);
UnmanagedMemory.free(struct);
}
}
}
Здравствуйте, Infernal, Вы писали:
I>Играюсь с GraalVM и прямому доступу к линуксу.
Мне кажется, что просто использовать CStruct для union не получится.
По поводу указателя, есть аннотация CPointerTo, мне кажется она как раз для этого.
Всем привет. Не сильно надеюсь, что будет ответ, но вдруг
Играюсь с GraalVM и прямому доступу к линуксу.
С вызовом функций с простыми типами, как mmap, strerror, ну и всяким прочим open/close/write/read проблем добраться и использовать нет.
Проблемы приши после попыток дотянуться до ioctl, а именно когда пришлось передавать стуктуры и указатели на структуру.
Скупая документация на GraalVM фактически сводится к одному примеру , который не особо помог с ответом.
А нужно протянуть в java что-то примерно такое:
typedef union my_union
{
uint8_t bb;
uint16_t ww;
uint8_t arr[32]; // <-- Проблема раз, как заалоцировать
} my_union;
typedef struct my_struct
{
char cc;
int size;
union my_union *data ; // <-- Проблема как создать и присобачить указатель на union тут
} my_struct;
В Graal это привращается во что-то такое (оно даже компиляется и запускается):
@CStruct("my_union")
public interface my_union extends PointerBase {
@CField("bb")
byte getBb();
@CField("bb")
void setBb(byte b);
@CField("ww")
short getWw();
@CField("ww")
void setWw(short word);
@CFieldAddress("arr")
Pointer getBlock(); // Какой тут тип должен быть?
}
@CStruct("my_struct")
public interface my_struct extends Pointer {
@CField("сс")
byte getСс();
@CField("сс")
void setСс(byte rw);
@CField("size")
int getSize();
@CField("size")
void setSize(int size);
@CFieldAddress("data")
CIntPointer getData(); // Какой тут тип должен быть? И как установить указатель на my_union
}
При передаче в таком виде, оно падает с ошибкой ioctl failed: -1
Соответственно вопросы:
1. Как правильно объявить структуры в GraalVM
2. Как правильно инициализировать и установить указатели.
Либо хотя бы как отдэбажить что native-image генерит(оно в момент трет исходики нативные) и что в ioctl пришло. Заранее благодарен за ответы.
Здравствуйте, StanislavK, Вы писали:
SK>Здравствуйте, Infernal, Вы писали:
I>>Играюсь с GraalVM и прямому доступу к линуксу. SK>Мне кажется, что просто использовать CStruct для union не получится. SK>По поводу указателя, есть аннотация CPointerTo, мне кажется она как раз для этого.
SK>JNI не подходит?
Тут как раз от него хочется отказаться.
Под JVM вполне все прекрасно выходит под сделать под JNA.
Сейчас осваиваю компиляцию того же кода, только в натив без всяких дополнительных нативных библиотек.
CPointerTo я видел, но с ходу не понял как его можно применить. Эта аннотация на интефейс, а не на поле в виде указателя. Сейчас вроде начало доходить, спасибо, попробую.
Походу придется копать в натив. По идее, зная размеры структур, оффсеты полей (это можно достать прямо через функции грааля, дабы не хардкодить), можно через malloc/free все замутить, если через аннотации не получится.
Здравствуйте, StanislavK, Вы писали:
SK>Здравствуйте, Infernal, Вы писали:
I>>Здравствуйте, StanislavK, Вы писали:
I>>CPointerTo я видел, но с ходу не понял как его можно применить. Эта аннотация на интефейс, а не на поле в виде указателя. Сейчас вроде начало доходить, спасибо, попробую. SK>Тут, как я понимаю, довольно много примеров: SK>https://github.com/oracle/graal/tree/master/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/headers
SK>В substratevm много чего есть.
Да, это я видел, маппинг некоторых функций, которые им самим похоже потребовались. Кое что оттуда вынес. Но с конкретной задачей это не помогло.
Проверил как Graal собирает struct/union на предмет размеров и offsets полей. Вроде для обоих типов правильно.
Но опять же при передаче — ошибка. Если знаете как посмотреть в линукс, что передалось в ioctl и получить дебаг информацию, то буду благодарен. Гугл не помог.
Здравствуйте, Infernal, Вы писали:
I>Проверил как Graal собирает struct/union на предмет размеров и offsets полей. Вроде для обоих типов правильно.
Мне кажется, что тогда для union надо задавать offset для каждого поля, иначе я не понимаю, как оно может работать.
I>Но опять же при передаче — ошибка. Если знаете как посмотреть в линукс, что передалось в ioctl и получить дебаг информацию, то буду благодарен. Гугл не помог.
А вот это: https://www.graalvm.org/reference-manual/native-image/DebugInfo/
ну и потом с dbg.
Здравствуйте, Infernal, Вы писали:
I>Проверил как Graal собирает struct/union на предмет размеров и offsets полей. Вроде для обоих типов правильно.
Правильно — это сколько? И как вы победили массив? В вашем примере у my_union размер должен быть 32 байта. И меня очень смущает стрелочка на arr в вопросе про аллокацию. Это же C, тот конкретный arr не нужно вообще аллоцировать. Стрелочка должна показывать на сам struct. Или в graal какие-то секретные аннотации есть?
I>Но опять же при передаче — ошибка. Если знаете как посмотреть в линукс, что передалось в ioctl и получить дебаг информацию, то буду благодарен. Гугл не помог.
Если только посмотреть — есть strace. Если еще пощупать — уже предложили gdb. Можно что-нибудь визуальное поверх него, например — ddd. Если инструментов нет — устанавливайте соответствующие пакеты, они почти во всех дистрибутивах должны быть.
Здравствуйте, maxkar, Вы писали:
M>Здравствуйте, Infernal, Вы писали:
I>>Проверил как Graal собирает struct/union на предмет размеров и offsets полей. Вроде для обоих типов правильно. M>Правильно — это сколько? И как вы победили массив? В вашем примере у my_union размер должен быть 32 байта. И меня очень смущает стрелочка на arr в вопросе про аллокацию. Это же C, тот конкретный arr не нужно вообще аллоцировать. Стрелочка должна показывать на сам struct. Или в graal какие-то секретные аннотации есть?
Проверил, в момент компиляции native-image все нормально все аллоцируется, грааль размер получает правильный.
I>>Но опять же при передаче — ошибка. Если знаете как посмотреть в линукс, что передалось в ioctl и получить дебаг информацию, то буду благодарен. Гугл не помог. M>Если только посмотреть — есть strace. Если еще пощупать — уже предложили gdb. Можно что-нибудь визуальное поверх него, например — ddd. Если инструментов нет — устанавливайте соответствующие пакеты, они почти во всех дистрибутивах должны быть.
Как предложил Станислав, через @CPointerTo struct/union прекрасно связались. Спасибо ему.
Пошел несколько дальше. Написал враппер в виде лайбрари на си, в котором вызываю ioctl.
Дергаю вызов одинаковых структур, с одинаковыми параметрами из си и структур из явы и сравниваю.
Размеры — одинаковые, данные — тоже. Проверял через GDB.
Единственная разница, в си указатели идут последовательно:
7ffffff150 — для структуры
7ffffff160 — для union
Для явы — нет:
5555e12a00
5555e127e0
Из Си все работает, в яве — ошибка.
Если делать то же самое под JNA, то решается как просто создаем вместо структуры Memory, заполняем и в качестве union кладем тоже Memory. Тогда все норм.
Есть подозрение, что надо тоже единый вектор памяти под структуры создавать и его передавать. Копаю дальше.