Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

UoKit.com Форумы _ UO Pilot _ ffi создание указателя на многомерный массив

Автор: DarkMaster 7.8.2022, 20:11

Собственно есть некоторый указатель на void либо просто number с адресом.
Нужно создать указатель на int[123][321] по этому адресу.
cast ругается на такие выкрутасы ну либо я что-то не так по синтаксису делаю.

Автор: Cockney 7.8.2022, 22:49

В плюсах (парсер ffi примерно от туда) нельзя кастануть void* к int[][], но вроде можно кастануть к указателю на указатель

Код
int **aptr = reinterpret_cast<int**>(void*)
aptr[100][200] = 0xdead


Цитата(Cockney @ 7.8.2022, 22:41) *

В плюсах (парсер ffi примерно от туда) нельзя кастануть void* к int[][], но вроде можно кастануть к указателю на указатель

Код
int **aptr = reinterpret_cast<int**>(void*)
aptr[100][200] = 0xdead



если адрес задан как int a = ...., то скорее всего придется допонительный каст делать

Код
reinterpret_cast<int**>(reinterpret_cast<void*>(a));

Автор: Cockney 7.8.2022, 23:40

еще вот такой урод можно испытать, сначала делаем

Код
using arr_type = int[500][500]; // max size


и проказничаем далее

Код
    void* ptr = 0;
    *(reinterpret_cast<arr_type*>(ptr))[100][5] = 80;

Автор: DarkMaster 8.8.2022, 1:12

орет invalid C type как только видит квадратные скобки внутри ffi.cast

причем прикастовать к int** не проблема... а вот размерности...

Автор: Cockney 8.8.2022, 1:20

А ескейп работает ? Типа \[\]

Автор: DarkMaster 8.8.2022, 1:29

Начинает орать про eof. Такое впечатление как-будто в чистый си строкой подставляет. Можешь написать именно через каст пример создания указателя на массив с размерностью?
я хз что есть reinterpret_cast и в чем разница...

Автор: Cockney 8.8.2022, 1:38

А в чем сакральный смысл каста именно к размерности ? Каст к ** и дальше индексируй.

Reinterpret_cast - "я тут главный, я знаю что это работает, повинуйся, машина" если оно не кастит, то вряд ли это возможно... но т.к. в плюсах возможно все, то просто сам каст будет иметь зубодробительную длину

А каст луа многое может делать, копирование памяти там, или еще че, это же не просто указка на уровне компиляции, это работа с объектами, имхо

Автор: DarkMaster 8.8.2022, 1:41

Цитата
А в чем сакральный смысл каста именно к размерности ? Каст к ** и дальше индексируй.

Чтобы первый индекс работал второй должен быть известен компилятору/интерпретатору.
Ну скажем прикастовал я к **, говорю дай мне элемент [5][2], а какой он по счету? Вторая размерность может быть 2, а может быть 10 и это будет совсем разный кусок памяти.

Автор: Cockney 8.8.2022, 1:52

Цитата(DarkMaster @ 8.8.2022, 1:41) *

Чтобы первый индекс работал второй должен быть известен компилятору/интерпретатору.
Ну скажем прикастовал я к **, говорю дай мне элемент [5][2], а какой он по счету? Вторая размерность может быть 2, а может быть 10 и это будет совсем разный кусок памяти.



Не понял мысли особо, но это вроде про рваные массивы. Да, по идеи тут не прокатит моя схема, но с другой стороны а как ты логически видишь каст простого числа к адресу конкретного элемента не зная инфы о массиве ? Компилятор логически это не сможет вывести никак только по индексам одного элемента.

Автор: Cockney 8.8.2022, 2:11

Тут парни чет нагородили

https://stackoverflow.com/questions/11869056/how-to-cast-simple-pointer-to-a-multidimensional-array-of-fixed-size

Автор: DarkMaster 8.8.2022, 2:39

Вот смотри, у нас есть некоторый *int и последовательно записаны числа 1, 2, 3, 4, 5, 6, 7, 8, 9.
Если мы этот инт прикастуем просто к **int - нам это ничего не даст, т.к. мы не сможем обратиться по индексу. Ну прикастовали, какое значение будет у элемента [2][2]? Это может быть и 4 и 5 и 6 и т.д, т.к. мы не сказали чему равна вторая размерность, а **int этой информации не содержит. Поэтому мне и нужен указатель на некоторый массив с фиксированной шириной, чтобы обращаться по индексам.

Автор: DarkMaster 8.8.2022, 3:05

https://stackoverflow.com/questions/1052818/create-a-pointer-to-two-dimensional-array
но как это применить в рамках ffi я честно говоря вообще хз...

Автор: Cockney 8.8.2022, 12:45

Могу только посочувствовать и пожелать успехов

Автор: DarkMaster 8.8.2022, 18:12

Если все-таки будет желание.
Наткнулся на такую весч:

Цитата
-- Declare a struct with a parameterized field type and name:
ffi.cdef([[
typedef struct { $ $; } foo_t;
]], type1, name1)

-- Anonymous struct with dynamic names:
local bar_t = ffi.typeof("struct { int $, $; }", name1, name2)
-- Derived pointer type:
local bar_ptr_t = ffi.typeof("$ *", bar_t)

-- Parameterized dimensions work even where a VLA won't work:
local matrix_t = ffi.typeof("uint8_t[$][$]", width, height)

Собственно из вышеописанного:
Код
local arr = ffi.typeof("int[$][$]", 10, 10)
log(tostring(arr))
arr[1][1] = 1

Создается некоторый объект, который вроде как указатель на правильный массив, но без адреса. Соответственно присвоение ничего не дает и выбивает ошибку, что не может индексивать чилом данный ctype.

Автор: Cockney 8.8.2022, 18:26

Цитата(DarkMaster @ 8.8.2022, 18:12) *

Если все-таки будет желание.
Наткнулся на такую весч:

Собственно из вышеописанного:
Код
local arr = ffi.typeof("int[$][$]", 10, 10)
log(tostring(arr))
arr[1][1] = 1

Создается некоторый объект, который вроде как указатель на правильный массив, но без адреса. Соответственно присвоение ничего не дает и выбивает ошибку, что не может индексивать чилом данный ctype.


Не, создается объект-тип, который дальше должен использоваться как
Код
void pass_arr_in_c(arr arrParam)
, например, или
Код
arr arr_cast(void* ptr)
, ну а дальше из луа обращаешься

Автор: DarkMaster 8.8.2022, 19:00

Цитата
void pass_arr_in_c(arr arrParam)

В таком варианте не понятно как его инициализировать перед передачей. Хотя сейчас не обо этом.
Цитата
arr arr_cast(void* ptr)

arr при этом должен быть объявлен в сdef. Как при этом может быть использван typeof не очень понимаю.
через ffi.cast с указанем этого типа индексируемый указатель создать не удалось.

Автор: Cockney 8.8.2022, 20:54

Сначала тайпдеф, потом создать объектом с типом arr, как int[50] только arr без размерности, ибо в дефе уже задано

Автор: DarkMaster 8.8.2022, 21:38

Так в ffi.cdef тайп дефе невозможно сделать что-то вроде:

Код
ffi.cdef[[
   typedef int[10][10] аrr_10_10;
]]

оно уже выбьет ошибку. Или я что-то не понял?

Автор: Cockney 8.8.2022, 22:55

Цитата(DarkMaster @ 8.8.2022, 21:38) *

Так в ffi.cdef тайп дефе невозможно сделать что-то вроде:
Код
ffi.cdef[[
   typedef int[10][10] аrr_10_10;
]]

оно уже выбьет ошибку. Или я что-то не понял?



Ffi.typeof()
Ffi.cdef и тут уже используешь тип arr_10_10

Автор: DarkMaster 8.8.2022, 23:46

Код
local arr = ffi.typeof("int[$][$]", 10, 10)
ffi.cdef[[
   typedef arr аrr_10_10;
]]

так что ли? declaration specifier expected near 'arr'
чувствую себя тормозом)

Автор: Cockney 8.8.2022, 23:58

Код
local arr_type = ffi.typeof("int[$][$]", 10, 10)
arr = ffi.new(arr_type)


типа того

Автор: DarkMaster 9.8.2022, 0:39

new создаст объект, а не указатель. Если в тип добавить *, то все равно создаст объект.
при
arr = arr+1
происходит превращение из int[10][10] в int*[10], но указатель дает двигать.
Т.е. по сути дела вроде как работать будет, но при этом будет мусорить изначальными объектами, которые потом вообще хрен удалишь скорее всего после таких приколов.

Автор: Cockney 9.8.2022, 0:58

Цитата(DarkMaster @ 9.8.2022, 0:39) *

new создаст объект, а не указатель. Если в тип добавить *, то все равно создаст объект.
при
arr = arr+1
происходит превращение из int[10][10] в int*[10], но указатель дает двигать.
Т.е. по сути дела вроде как работать будет, но при этом будет мусорить изначальными объектами, которые потом вообще хрен удалишь скорее всего после таких приколов.




значит нужно взять адрес объекта, чего скорее всего ffi не даст сделать

Автор: DarkMaster 9.8.2022, 1:23

Адрес могу предоставть - это не проблема. Проблема создать на него указатель. Собственно это и есть изначальная проблема.
У нас есть ctype, у нас есть адрес, есть снаружи созданный ctype по этому адресу. Проблема в том чтобы объяснить луа, что объект ctype лежит по такому-то адресу...
С другими типами это норм делалось через каст... А тут на ровном месте бред какакой-то...

Я результат не могу из либы вернуть... Ну точнее могу, но это будет int*, если делать по старой схеме. Обращение к элементам в итоге будет:
result[y*6+x] ну это же бред ппц...

Автор: Cockney 9.8.2022, 10:45

а из си можно сразу вернуть int[][] например так int[10][10] get() ? как тогда отработает обращение к результату вызова ?

Автор: DarkMaster 9.8.2022, 11:32

То упадет в обморок при виде скобок...

Автор: Cockney 9.8.2022, 17:11

Цитата(Cockney @ 8.8.2022, 23:58) *

Код
local arr_type = ffi.typeof("int[$][$]", 10, 10)
arr = ffi.new(arr_type)


типа того



А если сначала вызвать ffi.typeof, потом cdef в котором arr_type get() функция и потом это функцию вызвать, она отдаст адрес

Автор: DarkMaster 9.8.2022, 18:13

declaration specifier expected near 'arr_type'

Автор: Cockney 9.8.2022, 20:23

Напомни, а тайпдеф ты пробовал делать внутри cdef ?

Автор: Cockney 9.8.2022, 21:48

Код
 local ffi = require("ffi")
ffi.cdef([[
    typedef int int2d[10][10];
]])
local ptr = 0xDEAD
local arr = ffi.cast("int2d*", ptr)

Автор: DarkMaster 10.8.2022, 2:33

Спасибо. Чую долго бы я еще развлекался...
Итоговое безобразие получилось такое:

Код
local ffi = require("ffi")
ffi.cdef([[
    typedef int int2d[10];
]])

local int100 = ffi.new("int[100]")
for i = 0, 100 do
    int100[i] = i
end

local arr = ffi.cast("int2d*", int100)
log(tostring(arr[0][1]))
log(tostring(arr[1][1]))

Размерность сделал в typedef на одну меньше иначе пришлось бы указатель каждый раз разименовывать через [0] и по факту получить доп размерность. Фишки luajit.
указатель на int100 улетает в либу, результат в луа.

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)