26

Re: AHK: DllCall и правильный вызов функций.

wisgest пишет:
YMP пишет:

мне не нравятся вещи вроде

, Str, str)

Мне тоже. А вот так нравится

, "Str", str)

Какие все придирчивые.

27

Re: AHK: DllCall и правильный вызов функций.

MandarinKa02, это точно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

28 (изменено: Alectric, 2017-08-10 17:58:04)

Re: AHK: DllCall и правильный вызов функций.

Raven
Тоже работаю с сиеменсом, новичок в STL. К сожалению нет доступа к IP модулям чтобы "поиграться" со скриптами. Будет возможность обязательно попробую.

Raven пишет:

;а эти функции вообще не используются что ли?
PathCombine(abs, rel) {

Используется в начале при инициализации.

Raven пишет:

;а эти функции вообще не используются что ли?
BEint(ByRef Var, ByRef BE, Bytes) {
VarSetCapacity(BE, Bytes, 0)

loop, %Bytes%
{
byte := NumGet(Var, Bytes-A_Index, "UChar")
NumPut(byte, BE, A_Index-1, "UChar")

}
loop, %Bytes% {
MsgBox, % NumGet(BE, A_index - 1, "UChar")
}
}

Как я понял, BEint переворачивает данные (первый байт в конец, последний в начало) и выводит по одному байту в сообщении.
Берёт из переменной Var (может содержать сколько задашь байт) байт с конца и кладёт в переменную BE в начало, перебирая по одному байту. Видно что функция недоделанная, скорей всего использовалась для отладки.

Raven пишет:

buf := bit ;что это такое?
bufPtr := &buf

buf - номер читаемого бита, как я понял, или количество бит? Зачем там тогда area (область), значит читается какая-то область.


Функция S7_DBRead на мой взгляд практичнее - указываешь номер ДБ, откуда начать и сколько считать. Правда она тоже выглядит недописанной.

Можно увидеть твой текущий код?

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

29 (изменено: Alectric, 2017-08-10 18:18:20)

Re: AHK: DllCall и правильный вызов функций.

Всё сообразил что за area.

; S7Area
S7AreaPE := 0x81 	;Process Inputs.
S7AreaPA := 0x82 	;Process Outputs.
S7AreaMK := 0x83 	;Merkers.
S7AreaDB := 0x84 	;DB.
S7AreaCT := 0x1C 	;Counters.
S7AreaTM := 0x1D 	;Timers

Область памяти в ПЛК.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

30

Re: AHK: DllCall и правильный вызов функций.

Alectric Дык я ж эту функцию сам накорябал и пытаю ее. S7_DBRead как раз таки и требуется мне. С ней проще всего экспериментировать. Да и в контроллер лишнего не запишешь.

ret := ReadDB(obj, 110, 8, 4)
Msgbox %ret%
ReadDB(obj, db, start, size){
	VarSetCapacity(data, size, 0)
	DllCall("snap7.dll\Cli_DBRead", "UInt", obj, "Int", db, "int", start, "int", size, "str", data)
	return data
}

Я получаю с этой функции строки вида "Bkдд" "Bk{U" "BkuЗ" (4 байта (real значение в контроллере)). Я так понимаю сырые биты информации преобразуются в строку. По другому у меня никак не получилось получить данные... Не догоняю видимо я...
И вот что  чувак написал мне на гитхабе у которого я стырил изначальный код.

ReadDB returns binary data encoded in a string. Use NumGet to cast it to an integer. Also consider the Endianness. According to the official SNAP7 documentation, S7 uses Big Endian whereas "normal" computers use Little Endian. You will have to convert it manually in AHK

То есть как раз функция BEint и нужна для переворачивания байт так как в контроллерах сиеменс используется порядок байт "Big Endian".
Вообщем еще копать и копать. А на работе еще и работать иногда приходится ведь!

31 (изменено: Alectric, 2017-08-11 13:43:34)

Re: AHK: DllCall и правильный вызов функций.

Похоже на то, как я возился с КОМпортом. http://forum.script-coding.com/viewtopic.php?id=12659
Нужно воспринимать полученные данные не как текст, а как бинарные данные (он тебе так и ответил) и использовать NumGet для перевода данных в формат понятный для ahk.

 
      ; заполняем массив byte
        loop,% RS232_Bytes_Received*2
        {
          if (a_index&0x1)
          {
            bytenum:=(a_index-1)//2 ; номер байта

--------------> ; сам байт состоит из 2х символов HEX

            byte%bytenum%:=chr(numget(data,2*(a_index-1),"uchar")) . chr(numget(data,2*(a_index-1)+2,"uchar"))
          }
        }

     b7:="0x" byte7                    ; 1 байт
     i0:="0x" byte4 byte3         ; 2 байта
     w0:="0x" byte11 byte10 byte9 byte8 ; 4 байта

Зря с реала начал, начни лучше со слов или интегеров.

Полученные байты позднее можно будет разложить на нужные биты.

Raven пишет:

p7.dll\Cli_DBRead", "Ptr", obj,

Тут "Ptr" нужен.

RS232_Read(RS232_FileHandle,Data_Length,ByRef RS232_Bytes_Received)
{
  Num_Bytes:=Data_Length+Data_Length//3
  SetFormat,Integer,HEX
  VarSetCapacity(Data,Num_Bytes,0xff)
  if RS232_FileHandle
  Read_Result := DllCall("ReadFile"
       ,"ptr" , RS232_FileHandle   ; hFile
       ,"ptr"  , &Data             ; lpBuffer
       ,"Int"  , Num_Bytes        ; nNumberOfBytesToRead
       ,"ptr*", RS232_Bytes_Received   ; lpNumberOfBytesReceived
       ,"Int"  , 0)               ; lpOverlapped
  If (Read_Result != 1)
  {
    RS232_Close(RS232_FileHandle)
    COMFail=1
    return
  }
  Loop,% RS232_Bytes_Received
  {
    t:=NumGet(Data,a_index-1,"UChar")
    StringTrimLeft,t,t,2
    If (StrLen(t)=1)
      t:="0" t
    Data_HEX.=t
  }
  SetFormat,Integer,DEC
  Return Data_HEX
}

Переделал:

ReadDB(obj, db, start, size){
	VarSetCapacity(data, size, 0)
    SetFormat,Integer,HEX
	DllCall("snap7.dll\Cli_DBRead", "Ptr", obj, "Int", db, "int", start, "int", size, "ptr", &data)
    Loop,% size
    {
      t:=NumGet(Data,a_index-1,"UChar")
      StringTrimLeft,t,t,2
      If (StrLen(t)=1)
        t:="0" t
      Data_HEX.=t
    }
    SetFormat,Integer,DEC
	return Data_HEX
}

Есть вероятность что я где-то ошибся, возможно для функции библиотеки нужно все таки str:

ReadDB(obj, db, start, size){
	VarSetCapacity(data, size, 0)
    SetFormat,Integer,HEX
	DllCall("snap7.dll\Cli_DBRead", "Ptr", obj, "Int", db, "int", start, "int", size, "str", data)
    Loop,% size
    {
      t:=NumGet(Data,a_index-1,"UChar")
      StringTrimLeft,t,t,2
      If (StrLen(t)=1)
        t:="0" t
      Data_HEX.=t
    }
    SetFormat,Integer,DEC
	return Data_HEX
}
Raven пишет:

А на работе еще и работать иногда приходится ведь!

И не говори.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

32

Re: AHK: DllCall и правильный вызов функций.

Alectric Поздравляю коллега! у вас получилось то что не получалось у меня вот уже более недели
Обе функции возвращают одно и то же число. И то что я вижу в контроллере (DW#16#426AA2AB) ничем не отличается от получаемых данных(426AA2AB). Осталось придумать функции преобразования данных и можно писать свою скаду!

33 (изменено: Alectric, 2017-08-11 14:01:31)

Re: AHK: DllCall и правильный вызов функций.

Raven пишет:

свою скаду

Тоже мечтаю об этом, это же ужасно гибкие и бесплатные интерфейсы можно писать, работающие через эзернет!

Raven пишет:

  у вас получилось то что не получалось у меня вот уже более недели

Знал бы ты сколько я с КОМпортом возился.

Вот кстати про биты тему нашел, чтобы биты из байтов "вытягивать".
Как слово в реал преобразовать ума не приложу, голова кипит.

PS Тему наверно лучше переименовать: AHK: Siemens S7 через Ethernet в AHK.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

34 (изменено: Malcev, 2018-12-28 21:35:11)

Re: AHK: DllCall и правильный вызов функций.

У меня не вызывается следующая функция:
https://docs.opencv.org/2.4/modules/cor … reateimage

CreateImage

Creates an image header and allocates the image data.

C: IplImage* cvCreateImage(CvSize size, int depth, int channels)

Python: cv.CreateImage(size, depth, channels) → image
    Parameters:

        size – Image width and height
        depth – Bit depth of image elements. See IplImage for valid depths.
        channels – Number of channels per pixel. See IplImage for details. This function only creates images with interleaved channels.

Структура CvSize:

int width
int height

https://docs.opencv.org/ref/2.4/da/dcb/ … vSize.html

VarSetCapacity(cvsize, 8, 0)
NumPut(100, cvsize, 0, "int")
NumPut(100, cvsize, 4, "int")
msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "ptr", &cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
msgbox % a_LastError

Как правильно ее нужно вызывать?
Dll 32-bit:
https://ru.files.fm/u/6ny65dcr

35

Re: AHK: DllCall и правильный вызов функций.

На autoit же вызывается:

Local $cvsize = DllStructCreate("int;int")
DllStructSetData($cvsize, 1, 100)
DllStructSetData($cvsize, 2, 100)
Local $Result = DllCall("opencv_core2413.dll", "ptr:cdecl", "cvCreateImage" , "struct" , $cvsize , "int" , 8, "int" , 2)
MsgBox(1,1, $Result[0])

Баг автохотки?

36 (изменено: YMP, 2018-12-29 09:25:31)

Re: AHK: DllCall и правильный вызов функций.

Судя по всему, там передаётся сама структура, а не указатель на неё. Можно использовать int64.


width := 100
height := 100
cvsize := (height << 32) | width
msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "int64", cvsize, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
msgbox % a_LastError

37

Re: AHK: DllCall и правильный вызов функций.

Спасибо!
Не слышал о таком способе передачи структуры.
Гдве вы о нем узнали?

38

Re: AHK: DllCall и правильный вызов функций.

Уже и не помню. Обычно структуры по ссылке передаются, т.е. указателем. Не знаю, почему здесь решили передавать копию структуры, в чём тут выгода. Можно ещё разбить на два отдельных параметра.


width := 100
height := 100
msgbox % DllCall("opencv_core2413.dll\cvCreateImage", "int", width, "int", height, "int", IPL_DEPTH_8U := 8, "int", channels := 2, "Cdecl Ptr")
msgbox % a_LastError

Это работает, т.к. каждый простой параметр занимает в стеке 32 бита, так что эти числа будут лежать там рядом, как и в структуре. Но если бы функция была 64-битная, то там и простые параметры занимают 64 бита и уже бы этот способ не сработал для этой структуры.

39

Re: AHK: DllCall и правильный вызов функций.

YMP пишет:

передаётся сама структура

Как я понял, передается содержимое структуры?
А как быть, если структура достигает, к примеру 128,192 байта? Как ее содержимое передать? Или такое только в сказках?
P.S. В целях саморазвития.

40 (изменено: Malcev, 2018-12-29 17:18:47)

Re: AHK: DllCall и правильный вызов функций.

YMP, а если мы имеем структуру 4 элемента "Double".

double  d0,
double  d1 = 0,
double  d2 = 0,
double  d3 = 0

Как отдельные параметры они вроде передаются без ошибки, хотя вроде как 64 бита:

DllCall("opencv_core2413.dll\cvSet", "ptr", pimg, "Double", 255, "Double", 255, "Double", 255, "Double", 255, "ptr", 0, "Cdecl") 

Это вообще правильный и единственный вариант передачи структуры в данном случае, когда ссылка на структуру не передается?
И если у автоит передается всё стандартным объявлением структуры, а у автохотки нет, то, получается, это недочёт автохотки?

41

Re: AHK: DllCall и правильный вызов функций.

Malcev пишет:

Как отдельные параметры они вроде передаются без ошибки, хотя вроде как 64 бита:

В смысле double занимает 64 бита? Да, верно. Я имел в виду, что если функция 64-битная, а вы передаёте структуру из 32-битных целых, то при передаче отдельными аргументами каждое займёт в стеке 64 бита, т.е. они уже будут в памяти лежать не вплотную. Получится структура из 64-битных целых.

Т.е. если аргумент меньше 32 бит (для x86) или 64 бит (для x64), то под него всё равно выделяется 32 и 64 бита соответственно. А если он больше, то выделяется столько 32- или 64-битных ячеек, чтобы он влез.

Malcev пишет:

Это вообще правильный и единственный ли вариант передачи структуры в данном случае (как ссылка структура не передается)?

Да, правильный. Вероятно, единственный.

42

Re: AHK: DllCall и правильный вызов функций.

MandarinKa02 пишет:

А как быть, если структура достигает, к примеру 128,192 байта? Как ее содержимое передать? Или такое только в сказках?

Упаковывать по частям в те же int64 и передавать эти части как отдельные параметры. Бывает ли такое, не знаю. По идее, это неэкономично.

Тут, возможно, может помешать малопонятная мне неспособность АНК работать с беззнаковыми 64-битными целыми, т.е. uint64. Если при упаковке получится именно такое число, то не будет ли оно искажено впоследствии. Т.е. если в результате получится число 0x8000000000000000 или больше.

И если члены структуры разного типа, а именно целые и дробные, то тут не очень понятно, как их рассовать по int64.

43

Re: AHK: DllCall и правильный вызов функций.

YMP, понял. Благодарю за ответ.

44

Re: AHK: DllCall и правильный вызов функций.

Отписал в баг репорт, посмотрим, что ответят.

45 (изменено: YMP, 2018-12-29 17:56:34)

Re: AHK: DllCall и правильный вызов функций.

Но это, строго говоря, не баг, а отсутствие такой фичи (передачи самой структуры, а не указателя на неё). Это скорее в Wish List.

46

Re: AHK: DllCall и правильный вызов функций.

А автоит передает разве не указатель? Просто в нем при создании структуры нигде не надо указывать, что нужно передавать. Или он сам решает, что передавать?

47

Re: AHK: DllCall и правильный вызов функций.

Передавать нужно то, что ожидает функция. AutoIt передаёт саму структуру, если указан тип "struct", и ссылку если "struct*".

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

48

Re: AHK: DllCall и правильный вызов функций.

Точнее, не саму структуру, а копию. Т.е. передача по значению vs. передача по ссылке (указателем).

49

Re: AHK: DllCall и правильный вызов функций.

А где в функции обозначено, что ожидается передача копии структуры, а не указатель?

50 (изменено: YMP, 2018-12-29 19:40:20)

Re: AHK: DllCall и правильный вызов функций.

Там указан тип CvSize, а это структура. При указателе было бы CvSize *.

Хотя, конечно, могут и указатель на какой-то тип обозвать каким-то другим именем, тогда звёздочки не будет. Но какой-то намёк тогда в имени должен быть, вроде P или ptr. В общем, надо смотреть определение типа в документации.