Что нового

Как правильно передать массив в dll?

iamOmg

Новичок
Сообщения
97
Репутация
2
Изучаю PureBasic, пробую делать свою dll. Застопорился на том каким образом нужно передавать массив в dll?
Код:
Global $massiv1[5][10] = [[1,2,3,4,5,6,7,8,9,10], _
						  [1,2,3,4,5,6,7,8,9,10], _
						  [1,2,3,4,5,6,7,8,9,10], _
						  [1,2,3,4,5,6,7,8,9,10], _
						  [1,2,3,4,5,6,7,8,9,10]]
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Массив вы не сможете передать, передавайте структуру, точнее адрес на нее.
 
Автор
iamOmg

iamOmg

Новичок
Сообщения
97
Репутация
2
А можно массив в структуру записать?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
iamOmg,
Можно, например, примерно так сделать.
Код:
Local $aArray[5][10] = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],[11, 12, 13, 14, 15, 16, 17, 18, 19, 20],[21, 22, 23, 24, 25, 26, 27, 28, 29, 30], _
		[31, 32, 33, 34, 35, 36, 37, 38, 39, 40],[41, 42, 43, 44, 45, 46, 47, 48, 49, 50]], $s_TagTmp, $s_Tag, $t_Array, $i_Item, $i_Column

$i_Item = UBound($aArray)
$i_Column = UBound($aArray, 2)
$s_TagTmp = 'byte[' & $i_Column & '];'; or word or ...
For $i = 1 To $i_Item
	$s_Tag &= $s_TagTmp
Next
$t_Array = DllStructCreate($s_Tag)
For $i = 0 To $i_Item - 1
	For $j = 0 To $i_Column - 1
		DllStructSetData($t_Array, $i + 1, $aArray[$i][$j], $j + 1)
	Next
Next

;~ For $i = 0 To UBound($aArray) - 1
;~ 	For $j = 0 To UBound($aArray, 2) - 1
;~ 		ConsoleWrite($i & 'x' & $j & @TAB & DllStructGetData($t_Array, $i + 1, $j + 1) & @LF)
;~ 	Next
;~ Next

If DllOpen(@ScriptDir & '\test.dll') = -1 Then Exit 1
$a_Res = DllCall('test.dll', 'int', '_TestArray', 'struct*', $t_Array, 'word', $i_Item, 'word', $i_Column)
If @error Then Exit 2
ConsoleWrite('$a_Res[0]: ' & $a_Res[0] & @LF)
test.dll:
Код:
ProcedureDLL.l _TestArray(*p_StructStart, i_Item.u, i_Column.u)
  Protected i.l, s_Str$
  
  For i = 1 To i_Item
    For j = 0 To i_Column - 1
      s_Str$ + Str(PeekA(*p_StructStart + j)) + "|"
    Next
    *p_StructStart + i_Column
    s_Str$ + #CRLF$
  Next
  MessageRequester("Array", s_Str$)
  ProcedureReturn 1
EndProcedure
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Можно. Придумайте оптимальную структуру для вашей задачи и храните данные в ней. Здесь все зависит от конкретной задачи. В PB вам придется создать такую же структуру.

madmasles , это плохой пример. :smile:
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Я думаю лучше передать структуру с указателями на другие структуры.
 

Prog

Продвинутый
Сообщения
537
Репутация
65
madmasles [?]
Немного доработал. PeekA заменил на массив в структуре. По моему так код нагляднее.
Код:
Structure ArrA
  Arr.a[0]
EndStructure

ProcedureDLL _TestArray(*p_StructStart.ArrA, i_Item.u, i_Column.u)
  Protected i, j, s_Str$, Index=0
  
  For i = 1 To i_Item
    For j = 1 To i_Column
      s_Str$ + Str(*p_StructStart\Arr[Index]) + "|"
      Index+1
    Next
    s_Str$ + #CRLF$
  Next
  MessageRequester("Array", s_Str$)
  ProcedureReturn 1
EndProcedure
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
madmasles [?]
Можно, например, примерно так сделать.
Интересно, с этого можно построить что то типа ArrayToStruct и обратно, StructToArray? :scratch:
 
Автор
iamOmg

iamOmg

Новичок
Сообщения
97
Репутация
2
Что-то не совсем понял, тут вроде как одномерная структура всмысле массив
Код:
Structure ArrA
  Arr.w[0]
EndStructure
Как он обращается к массиву в структуре по одной цифре в индексе, а если массив двухмерный?
Код:
 s_Str$ + Str(*p_StructStart\Arr[Index]) + "|"
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
CreatoR сказал(а):
Интересно, с этого можно построить что то типа ArrayToStruct и обратно, StructToArray?
В этом нет смысла, нужно подстраивать AutoIt код, иначе теряется весь смысл использования .dll. Какой смысл преобразовывать массив в структуру перед вызовом функции, а потом обратно структуру в массив?


Добавлено:
Сообщение автоматически объединено:

iamOmg сказал(а):
Как он обращается к массиву в структуре по одной цифре в индексе?
ArrA, это просто тип данных, а обращается он по адресу - "*".
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
iamOmg [?]
Как он обращается к массиву в структуре по одной цифре в индексе, а если массив двухмерный?
Примерно так (если на AutoIt).
Код:
#include <Array.au3>

Local $aArray[5][10] = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],[11, 12, 13, 14, 15, 16, 17, 18, 19, 20],[21, 22, 23, 24, 25, 26, 27, 28, 29, 30], _
		[31, 32, 33, 34, 35, 36, 37, 38, 39, 40],[41, 42, 43, 44, 45, 46, 47, 48, 49, 50]], $i_Item, $i_Column

$i_Item = UBound($aArray)
$i_Column = UBound($aArray, 2)

Local $aArrayOne[$i_Item * $i_Column], $i_Index

For $i = 0 To $i_Item - 1
	For $j = 0 To $i_Column - 1
		$aArrayOne[$i_Index] = $aArray[$i][$j]
		$i_Index += 1
	Next
Next
_ArrayDisplay($aArrayOne)
 
Автор
iamOmg

iamOmg

Новичок
Сообщения
97
Репутация
2
Понятно, со структурами совсем по другому работать нужно, не так как с массивами
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
теряется весь смысл использования .dll
Я не для Dll, мне это больше из интереса, например для передачи указателя на структуру массива в PostMessage.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR [?]
мне это больше из интереса, например для передачи указателя на структуру массива в PostMessage
Если все данные однотипные, то пример я показал, если типы в массиве разные, то надо, ИМХО, передавать в функцию строку с типами данных, выравнивать структуру и т.д. и т.п.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
ИМХО, в AutoIt использовать структуры нужно только для вызова API функций, а так лучше всего массивы.
 

Prog

Продвинутый
Сообщения
537
Репутация
65
В структуре также может быть массив. Если нужно, то многомерный. Код для случая
Код:
$aArray[5][10]
будет таким.
Код:
Structure SubArrA
  Arr.a[10]
EndStructure

Structure ArrA
  Arr.SubArrA[5]
EndStructure

ProcedureDLL _TestArray(*p_StructStart.ArrA, i_Item.u, i_Column.u)
  Protected i, j, s_Str$
  
  For i = 0 To i_Item-1
    For j = 0 To i_Column-1
      s_Str$ + Str(*p_StructStart\Arr[i]\Arr[j]) + "|"
    Next
    s_Str$ + #CRLF$
  Next
  MessageRequester("Array", s_Str$)
  
EndProcedure

Если все данные однотипные, то пример я показал, если типы в массиве разные, то надо, ИМХО, передавать в функцию строку с типами данных, выравнивать структуру и т.д. и т.п.
Если заранее известны типы в структуре, то строку передавать не обязательно. Можно передать лишь структуру.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
madmasles [?]
ИМХО, в AutoIt использовать структуры нужно только для вызова API функций
ИМХО, это как раз таки досадно, потому как структура удобнее в использовании.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Есть непрерывный блок памяти, а структура просто указывает, как именно располагаются данные в этом блоке. Поэтому, технически, структура может содержать что угодно, хоть массивы, хоть строки разной длины. В AutoIt работать со структурами крайне неудобно, поскольку для этого нет нативных средств кроме DllStruct... А вот с массивами вкупе с типом Variant работать одно удовольствие. Разумеется в рамках скрипта.
 
Верх