Версия для печати темы
UoKit.com Форумы _ UO Pilot _ Lua number -> pointer cast
Автор: Cockney 5.11.2019, 13:16
Вопрос знатокам.
Есть ffi.cdef
Код
struct image_descriptor {
unsigned char* address;
int width;
int height;
int length;
};
далее
Код
local a,w,h,l = getimage()
local img_descr = ffi.cast("struct image_descriptor*")
img_descr.address = a
Получаем ошибку. Собственно, на сколько я понял, в документации написано : только number -> number, pointer -> pointer, иные варианты не допустимы.
Как выкручиваться ?
Автор: DarkMaster 5.11.2019, 15:01
Потому что ты указателю присваиваешь строку. Не по адресу указателя, а в сам указатель.
Автор: Cockney 5.11.2019, 18:49
Какая строка ? Getimage возвращает address как строку ? Так или иначе, можно правильный код ?
Автор: DarkMaster 6.11.2019, 2:37
Вот тебе оно реально надо с типами мозг насиловать? Любой указатель есть int.
Код
ffi.cdef[[
typedef struct {
int address;
int width;
int height;
int length;
} image_descriptor;
]]
local a,w,h,l = getimage(100,100,220,220)
local img_descr = ffi.new("image_descriptor")
img_descr.address = a
Автор: Cockney 6.11.2019, 22:12
в частном случае - да, но тем не менее, сам факт такого костыля...искажает суть написанного, если писал не ты.
Автор: DarkMaster 14.11.2019, 12:05
Я не сомневаюсь, что можно сделать нормально, но тут уж я виноват - всегда непереносил С за переименование базовых типов.
Автор: Cockney 14.11.2019, 15:39
Си здесь не причем. Тут нет никакого переименования типов. Например, unsigned char есть по сути тип byte, т.е. аллиас. А что ты предложил - просто каст любого числа, и не просто любого, а знакового, к поинтеру(он же uintptr_t, uint32_t). Т.е. в том int может лежать -1 и это спокойно уйдет в длл, где воспримется как невалидный поинтер. Можно еще вспомнить про размер указателя, но это не так опасно как описанное выше.
Автор: DarkMaster 14.11.2019, 16:38
А указателю ты =1 не присвоишь? Что-то мне подсказывает, что он все-таки обычный инт а не unsigned, ибо на 32 битах ограничение 2гб, а не 4. Если не присвоишь, то это вопрос доб оберток и safe функций. Ну типа круто, все такое, но в моем понимании, если ты лезешь писать на Си, то ты должен понимать, что делаешь и как ты вообще допустил туда -1. Для меня все-таки (пусть это с точки зрения терминологии ппц ваще как не правильно) обычное переименование, алиас или еще что-то. Если значение в памяти занимает одинаковое количество байт и способ записи не меняется, а названий (способов объявления) много, то для меня это становится некоторым сомнительным решенем, особенно когда вызывает конфликты кастов при том, что в памяти эти "разные" типы выглядят идентично. Не фанат я таких решений. Для меня это сокрытие от пользователя природы вещей и дистанцирование от базы. Все выше описанное личное мнение и не более того.
Автор: Cockney 14.11.2019, 17:03
Цитата
А указателю ты =1 не присвоишь?
Именно 1? Присвою ,конечно, только он все равно не валидный. Вообще история с signed/unsigned для того, чтобы благополучно получить эксепшн(ошибку компиляции) в ходе арифметики с указателями, а не лезть сразу по отрицательному.
Цитата
если ты лезешь писать на Си, то ты должен понимать, что делаешь и как ты вообще допустил туда -1
А вот и нет. Сама система типов не даст без явных кастов пропихнуть -1 как адрес. Получишь минимум ворнинг. А вот в int, который уже в моей длл будет выглядеть как поинтер - пожалуйста.
Т.е. в идеале в скрипте нельзя указателю присвоить -1 и в длл тоже нельзя. Получим то что хотели, а щас я могу лишь надеться(написать обертку) что данные валидные.
Цитата
Если значение в памяти занимает одинаковое количество байт и способ записи не меняется а названий (способов объявления) много, то для меня это становится некоторым сомнительным решенем, особенно когда вызывает конфликты кастов при том, что в памяти эти "разные" типы выглядят идентично
Как int32 может быть равен uint32 ? И там и там 4 байта, диапазоны разные, а уж инструкции для работы с ними тем более. Так например, побитовый сдвиг для signed сохраняет знаковый бит, а для unsignned - нет. Тоже сложение, для одного результатом может стать переполнение, для другого просто неверный результат. Таких отличий - море. Другой вопрос, когда появляются аллиасы UINT, UINT32, DWORD, QWORD и так далее, вот тут уже перебор.
К слову, для ясности, int, unsigned int - фундаментальные типы, т.е. априори они не одно и тоже. int32_t и uint32_t лишь удобные аллиасы для них. а вот DWORD(uint32) уже аллиас, который не нужен.
Автор: DarkMaster 14.11.2019, 17:51
Цитата
Именно 1?
Шифт. -1 естественно. У меня студии под рукой нет. Мне прям интересно даст ли присвоить именно на стадии компиляции -1 указателю.
Цитата
А вот и нет. Сама система типов не даст без явных кастов пропихнуть -1 как адрес. Получишь минимум ворнинг. А вот в int, который уже в моей длл будет выглядеть как поинтер - пожалуйста.
Вот есть как раз подозрение, что это как максимум. Не уверн в том, что будет ошибка компиляции и совсем не уверен будет ли хоть какая-то разница в бинарнике.
Цитата
К слову, для ясности, int, unsigned int - фундаментальные типы, т.е. априори они не одно и тоже.
Я с Сями хоть и на вы, но не настолько же) Уж как в памяти это выглядит я себе представляю и там разница в одном бите который определяет знак либо значение разряда в зависимости от типа.
Я не говорю, что это одно и то же, я говорю о том, что, как я помню указатель является int'ом, а не uint'ом, т.к. ограничение по диапазону значений соответсвует int, так же учитывая скорость обработки знаковых и беззнаковых типов намекает на то, что делать указатель беззнаковым типом к большой потере производительности. Это одна из причин, почему я очень сильно сомневаюсь в получении эксепшена в откомпиленной программе и ворнинг компилятора скорее все, что мы получим (речь естественно о присвоении, а не про обращение по адресу).
Цитата
К слову, для ясности, int, unsigned int - фундаментальные типы, т.е. априори они не одно и тоже.
Так же речь была именно про одинаковые в памяти вещи. Самый поверхностный вариант ты уже привел - byte. Можно еще открыть winapi и посмотреть какая там радость наворочена. Достаточно вспомнить отсылку сообщений когда отсылаются два параметра по два байта. Беззановые. Думаешь unsigned word там будет?) И так со всем.
Автор: Cockney 14.11.2019, 22:48
Цитата
Мне прям интересно даст ли присвоить именно на стадии компиляции -1 указателю.
Если в тупую - void* memPtr = -1, то не даст, невозможно кастануть int к void*. Если явно - void* memPtr = (void*)-1, то -1 приведет к max uint64, что странно, ибо компилировал под x32, но так или иначе, -1 превращается в верхнюю границу типа.
Цитата
как я помню указатель является int'ом, а не uint'ом
Если исходить из того, что в машине нельзя обращаться по отрицательным адресам (а int подразумевает хранение таковых) он конечно может быть указателем но на определенном диапозоне, пусть даже и совпадает от 0 до max с максимальным адресом системы, но в качестве безопасности интерфейса общения разных интерфейсов я бы лично использовал uint для этого. В качестве отступления : в c++11 есть два типа указателей intptr_t и uintptr_t, для чего - написано где-то в стандарте
Впервые слышу, чтобы знак как-то влиял на производительность.
Цитата
winapi
winapi - не си, там своя атмосфера и "особый путь".
Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)