Что нового

DllStructCreate - правильное создание структуры

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
как правильно использовать типы данных?
мне нужно передать "слово" или число . какой тип данных использовать?
в справке пример char var4[128] для "слова" ,по некоторым кодам я видел что используется и wchar. только два этих типа данных используются для передачи слова?
мне нужно поместить данные (слова и числа) в одной структуре - есть ли порядок следования ?
какое количество данных можно поместить в структуру?
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
joiner [?]
в справке пример char var4[128] для "слова" ,по некоторым кодам я видел что используется и wchar. только два этих типа данных используются для передачи слова?
В зависимости от того, куда тебе нужно это слово передать. Структура и ее размер должны быть фиксированы, а иначе как стороннее приложение узнает как ее считать(Длинна и типы данных).
Код:
CHAR	 8 бит (1 байт) ASCII символ
WCHAR	 16 бит (2 байта) UNICODE широкий символ
Слово - это массив (char/wchar/...).

какое количество данных можно поместить в структуру?
Да сколько угодно, хотя насколько я знаю ограничение есть: (2^40)-1

Поэтому обычно в начало структуры записывают ее размер, а стороннее приложение считав размер - читает структуру(в твоем случае массив переменной длинны).
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
firex [?]
Поэтому обычно в начало структуры записывают ее размер, а стороннее приложение считав размер - читает структуру(в твоем случае массив переменной длинны).
зачем указывать размер? разве без размера нельзя считать данные?
можно пример ?
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Вы должны знать формат структуры, она должна быть как то описана.
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
joiner [?]
зачем указывать размер? разве без размера нельзя считать данные?

Можно, пример:

Код:
GetData(CreateData('Пример', 264))

Func CreateData($sText, $iNumber)
	Local $iSize = StringLen($sText)
	$tBuffer = DllStructCreate('uint;byte[' & $iSize & '];int')
	DllStructSetData($tBuffer, 1, $iSize)
	DllStructSetData($tBuffer, 2, $sText)
	DllStructSetData($tBuffer, 3, $iNumber)
	Return $tBuffer
EndFunc

Func GetData($pBuffer)
	$tSize = DllStructCreate('uint', DllStructGetPtr($pBuffer))

	$tBuffer = DllStructCreate('byte[' & DllStructGetData($tSize, 1) & '];int', (DllStructGetPtr($pBuffer) + DllStructGetSize($tSize)))

	MsgBox(0, '', 'Text: ' & BinaryToString(DllStructGetData($tBuffer, 1)) & @CRLF & _
	              'Number: ' & DllStructGetData($tBuffer, 2))
EndFunc
 

sims

Осваивающий
Сообщения
184
Репутация
24
joiner [?]
мне нужно передать "слово" или число . какой тип данных использовать?
Строковой тип или массив символов. Но можно и массив байт.

мне нужно поместить данные (слова и числа) в одной структуре - есть ли порядок следования ?
Можно.
Порядок следования должен быть такой же как и на принимающей стороне, иначе "моя твоя не понимать".

какое количество данных можно поместить в структуру?
Сколько хватит оперативки. Но не стоит забывать что в x86 системах, процесс не может запросить больше 2 ГБ ОЗУ.

Viktor1703 [?]
В AutoIt работа со структурами через одно место. Неужели разробы не могли сделать более адекватную поддержку структур?
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
joiner [?]
какое количество данных можно поместить в структуру?

Смотря для чего, если для передачи структуры по сети (TCP) то не более 65535 байт...

sims [?]
В AutoIt работа со структурами через одно место. Неужели разробы не могли сделать более адекватную поддержку структур?

Это потому что AutoIt интерпретируемый в отличии от пурика.
 

sims

Осваивающий
Сообщения
184
Репутация
24
MnM [?]
что такое "разробы" ?
Разработчики. В нашем случае - разработчики AutoIt.

Viktor1703 [?]
Это потому что AutoIt интерпретируемый в отличии от пурика.
Я имел в виду C++ или Дельфи, но даже в PB, работа со структурами намного логичнее и нагляднее чем в AutoIt.
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
sims [?]
но даже в PB, работа со структурами намного логичнее

Согласен...., но в PB нельзя динамически создавать структуру, то есть структура должна быть за раннее определена, это касается типа с фиксированными размерами данных, хотя, это не проблема....

Код:
Structure TBUFFER
  size.l
  number.i
EndStructure

Procedure CreateData(Text.s, Number.i)
  Protected buffer.TBUFFER, *tBuffer, size.q
  
  size = StringByteLength(Text)
  If size
    *tBuffer = AllocateMemory(size + SizeOf(TBUFFER))
    If *tBuffer
      buffer\size   = size
      buffer\number = Number
      CopyMemory(@buffer, *tBuffer, SizeOf(TBUFFER))
      CopyMemory(@Text, (*tBuffer + SizeOf(TBUFFER)), size)
      ProcedureReturn *tBuffer
    EndIf
  EndIf
  ProcedureReturn 0
EndProcedure  

Procedure GetData(*mem)
  Protected buffer.TBUFFER
  If *mem
    CopyMemory(*mem, @buffer, SizeOf(TBUFFER))
    MessageRequester("", "Text: " + PeekS((*mem + SizeOf(TBUFFER)), buffer\size) + #CRLF$ + "Number: " + Str(buffer\number))
  EndIf  
EndProcedure  

*mem = CreateData("Пример", 264)
If *mem
  GetData(*mem)
  FreeMemory(*mem)
EndIf
 

sims

Осваивающий
Сообщения
184
Репутация
24
Это если "дословно перевести" с AutoIt, но подобный способ хранения данных непосредственно в структуре, необходим не так часто.
Обычно динамически изменяемые данные, не хранят в структуре. В место этого, в ней находится указатель на данные.
Пример правильнее перевести таким образом.
Код:
Structure tBuffer
  iSize.i
  sText.s
  iNumber.i
EndStructure

Procedure CreateData(sText.s, iNumber.i, *Buffer.tBuffer)
  If *Buffer
    *Buffer\iSize   = Len(sText)
    *Buffer\sText   = sText
    *Buffer\iNumber = iNumber
  EndIf
EndProcedure

Procedure GetData(*Buffer.tBuffer)
  If *Buffer
    MessageRequester("", "Text: "+*Buffer\sText+#CRLF$+
                         "Number: "+*Buffer\iNumber)
  EndIf
EndProcedure

Buff.tBuffer
CreateData("Пример", 264, @Buff)
GetData(@Buff)
А если нужно полное соответствие (процедура создает и возвращает структуру), то код будет таким.
Код:
Structure tBuffer
  iSize.i
  sText.s
  iNumber.i
EndStructure

Procedure CreateData(sText.s, iNumber.i)
  *Buffer.tBuffer = AllocateMemory(SizeOf(tBuffer))
  If *Buffer
    InitializeStructure(*Buffer, tBuffer)
    *Buffer\iSize   = Len(sText)
    *Buffer\sText   = sText
    *Buffer\iNumber = iNumber
  EndIf
  ProcedureReturn *Buffer
EndProcedure

Procedure GetData(*Buffer.tBuffer)
  If *Buffer
    MessageRequester("", "Text: "+*Buffer\sText+#CRLF$+
                         "Number: "+*Buffer\iNumber)
    ClearStructure(*Buffer, tBuffer)
    FreeMemory(*Buffer)
  EndIf
EndProcedure


GetData(CreateData("Пример", 264))
В данном примере, поле iSize структуры, не нужно (длину строки в структуре можно узнать используя функцию Len()) и оставлено только для совместимости.
Еще одно преимущество такого метода в том, что длину строки можно изменять как угодно, а в AutoIt жестко задан размер под строку.
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
ребята, спасибо, конечно , за ответы, но не превращайте тему в обсуждение недостатков и достоинств языков программирования.
я знаю только autoit . поэтому мои вопросы касаются только его.

[?]
$tBuffer = DllStructCreate('uint;byte[' & $iSize & '];int')
Viktor1703 , ты определяешь размер массива исходя из количества символов в строке? то есть
размер массива определяется не в байтах?
[?]
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
joiner

По другому ни как, если работать именно со структурой, то нужно явно указывать размеры данных, для того что бы считать эти данные из структуры.

Для начала нам нужно создать структуру определённого размера, она не расширяется динамически в зависимости от количества записанных данных, но чтобы узнать какого размера нам нужна структура, мы сначала определяем размер данных, далее создаём структуру, в первую ячейку мы записываем размер этих данных, далее сам текст, при приёме такого пакета, нам для начала нужно узнать сколько байт считать из структуры, для этого мы считываем первые 4 байта и узнаём размер текста хранящегося в структуре, после чего переходим к самим данным, всё это для того чтобы не выходить за рамки выделенной области памяти и не читать данные из другой ячейки памяти.
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Viktor1703
для чего используется
Pointer [опционально] Если структуре не выделена память, но используется указатель.
как я понял из справки, если не выделена память ( а значит нет указан размер структуры вначале), то используется указатель на уже выделенную память.
 

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
joiner

Я что - то запутался, что конкретно требуется?

Код:
$tBuffer = DllStructCreate('int;int;wchar;int')
DllStructSetData($tBuffer, 1, 1000)
DllStructSetData($tBuffer, 2, 1001)
DllStructSetData($tBuffer, 3, 'Текст который мы больше не увидем')
DllStructSetData($tBuffer, 4, 1002)

MsgBox(0, '', DllStructGetData($tBuffer, 1) & @CRLF & _
              DllStructGetData($tBuffer, 2) & @CRLF & _
			  DllStructGetData($tBuffer, 3) & @CRLF & _
			  DllStructGetData($tBuffer, 4))

$tRead = DllStructCreate('int;int;wchar;int', DllStructGetPtr($tBuffer))

MsgBox(0, '', DllStructGetData($tRead, 1) & @CRLF & _
              DllStructGetData($tRead, 2) & @CRLF & _
			  DllStructGetData($tRead, 3) & @CRLF & _
			  DllStructGetData($tRead, 4))
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Viktor1703 [?]
Я что - то запутался, что конкретно требуется?
конкретно:
[?]
в справке пример char var4[128] для "слова" ,по некоторым кодам я видел что используется и wchar. только два этих типа данных используются для передачи слова?

второе:
если есть указатель в DllStructCreate - pointer,
Код:
$tRead = DllStructCreate('int;int;wchar;int', DllStructGetPtr($tBuffer))

то не нужно указывать размер структуры вначале. так?


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

и еще
Код:
Local $iSize = StringLen($sText)
    $tBuffer = DllStructCreate('uint;byte[' & $iSize & '];int')

размер массива данных определяется в байтах или в количестве знаков? ведь как я понял функция StringLen возвращает количество символов в строке
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
joiner
Насколько я знаю, должен указан максимальный размер помещаемых данных. Например если структура хранит путь к файлу, то размер должен быть 260 или 32767. Когда WinAPI функция помещает туда данные она наверно добавляет Null (0x00) cимвол в конец строки и при считывании получает только сам путь, а не все 32767. В Си - Null (0x00) является конец строки для строковых функций. А размер максимально допустимый, чтобы не был обрезан. Для чисел размер определяется типом, то есть взависимости от границ числа, которые помещаются.

Указатель нужен для того чтобы передать структуру функции WinAPI. Как бы дать адрес где находится структура в памяти. Указатель не определяет размер, он указывает начало данных структуры или начало отсчёта.
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
в принципе я использую создание структуры с указателем, который получаю из WinApi - функции.
я вижу , что в данном случае вначале структуры не указывается ее размер, так как функция Api уже создала объект определенного размера. а если нет указателя, то нужно указывать размер вначале структуры. с этим понятно.
в справке говорится, что "[ ]" используется для создания массива данных . мой вопрос был:
используется количество символов в строке или размер в байтах?
это я про пример Viktor1703.
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
joiner [?]
используется количество символов в строке или размер в байтах?
Можно использовать хоть в байтах хоть в символах, Просто посчитайте сколько символов будет в байте и вам станет ясно сколько байт выделить или сколько символов выделить. А для структуры это ровно, типом определяется размер ячейки, а в памяти это одна большая строка типа "00001010010101010101" и только сама структура определит, где расставить границы на этой строке. Вы можете указать другую структуру, тогда эти же данные будут разграничены в соответствии с теми границами, которая указывает структура.
 
Верх