Что нового

Создание структуры и вывод данных из структуры (по исходникам dll)

o_nix

Новичок
Сообщения
35
Репутация
1
Собственно уже 2й день бьюсь над запуском dll
http://autoit-script.ru/index.php?action=dlattach;topic=169.0;attach=412

Сначала ндолго немог понять почему dll всегда возвращает в ответе 0
Потом почитав эту ветку http://autoit-script.ru/index.php/topic,788.0.html
додумался что для работы с этой dll нужно создавать структуру данных но как это сделать я исходя из имеющейся информации непонимаю.

Имеем код
Код:
$Dll = DllOpen("CaptchaServices.dll")

$otvet_dll = DllStructCreate("char ident;long errore") ; char здесь указанно только изза того что при указании str структура вообще несоздаётся.
if @error Then
    MsgBox(0,"","Ошибка создания структуры " & @error)
    exit
endif

DllCall($Dll, "int", "Init", "str", "login","str", "password")

$rezult = DllCall($Dll, "int", "RecognizeFromFile", "str", "captcha.jpg", "str", DllStructGetPtr($otvet_dll, "ident"), "long", DllStructGetPtr($otvet_dll, "errore"))
If Not @error Then
		
$id = DllStructGetData($otvet_dll, "ident")
        MsgBox(64, "ID капчи", $id)
Else
    MsgBox(16, 'Ошибка', 'DllCall Error (' & @error & ')')
EndIf


Почему возвращается пустое значение $id ??

Судя по исходникам dll
Код:
// Recognizes captcha from file. 
// Loads file from disk and calls RegognizeFromMem (see below for details).
CS_API int WINAPI RecognizeFromFile(LPCSTR pszFileName, LPSTR& pszText, long* plErr);

И readme
Код:
int RecognizeFromFile(LPCSTR pszFileName, LPSTR& pszText, long* plErr)

строка вызова функции составлена правильно
$rezult = DllCall($Dll, "int", "RecognizeFromFile", "str", "captcha.jpg", "str", DllStructGetPtr($otvet_dll, "ident"), "long", DllStructGetPtr($otvet_dll, "errore"))

Файл капчи отсылается на сервис распознавания но в ответ я немогу получить ни id ни код ошибки выданный dll
Сама dll ошибку невозвращает - тоесть якобы в ней внутри всё прошло в штатном режиме.

вопрос что такое long* - что конкретно эта звёздочка обозначает и поддерживает ли это AutoIT ??

почему при указании структуры
Код:
$otvet_dll = DllStructCreate("str ident;long errore")

структура несоздаётся ??
Судя по
Код:
LPSTR& pszText, long* plErr
мне необходимо создать структуру содержащую два поля типов str и long ....

В общем я непонимаю почему у меня неделает того что должно делать ... помогите пожалуйста ...

Конкретно интерисующий вопрос это:
1. Создание структуры под конкретную dll по её исходникам или api (как где что откуда и почему)
2. Вызов функции из dll с записью данных в указанные ячейки структуры
3. Вывод этих данных в переменную пригодную для дальнейшего использования в AutoIT"

Полностью readme
Описание функций CaptchaServices.dll

----------------------------------------------------------------------------------------------

CaptchaServices.dll предоставляет 2 типа сервиса для распознавания изображений.
Первый тип - набор экспортируемых функций, второй тип - тот же функционал, но реализованный
через COM объект.


1. Экспортируемые функции
-------------------------

1.1. void Init(IN LPCSTR pszLogin, IN LPCSTR pszPasswd)
Данная функция всегда должна вызываться первой. Устанавливает имя пользователя и
пароль для доступа на сервер распознавания изображений.


1.2. int RecognizeFromFile(LPCSTR pszFileName, LPSTR& pszText, long* plErr)
Функция распознавания изображения из файла.

Параметры:

pszFileName
[in] - Имя файла для распознавания.

pszText
[out] - результат распознавания. Результирующий текст отводится в куче,
соответственно в какой то момент должен быть освобожден. Это можно
сделать с помощью функции Free (см. ниже).
plErr
[out] - возвращает код ошибки. Может быть NULL если код ошибки не требуется.


Возвращаемое значение:

Возвращает идентификатор изображения. Используется в функции Report.


1.3. int RecognizeFromMem(BYTE* pImage, UINT nSize, LPSTR& pszText, long* plErr)
Функция распознавания изображения из памяти.

Параметры:

pImage
[in] - двоичное содержание изображения.

nSize
[in] - размер буфера pImage в байтах.

pszText
[out] - результат распознавания. Результирующий текст отводится в куче,
соответственно в какой то момент должен быть освобожден. Это
можно сделать с помощью функции Free (см. ниже).
plErr
[out] - возвращает код ошибки. Может быть NULL если код ошибки не требуется.


Возвращаемое значение:

Возвращает идентификатор изображения. Используется в функции Report.

1.4. void Report(long lId, bool bRecognized)
Функция предназначена для сообщения на сервер о правильности распознавания изображения.

Параметры:

lId
[in] - Идентификатор изображения возвращаемый функциями RecognizeFromFile и
RecognizeFromMem.

bRecognized
[in] - Истино ли распознавание. true - да, false - нет.

1.5. void Free(LPSTR pszText)
Освобождает память отведенную в функциях RecognizeFromFile и RecognizeFromMem. Имеет
смысл если модуль используйщий эти функции и CaptchaServices.dll собраны с разными CRT.


2. Методы COM объекта
---------------------

Функционал перечисленный в п.1 дублирован методами COM объекта. Предназначен как для
скриптовых языков не способных импортировать функции из DLL, так и для приложений
имеющих компонентную архитектуру.

Имя COM класса: CaptchaServices.CaptchaRecognizer
GUID COM класса: 67DC9B1A-087D-4FA2-BF5D-0A88C0AAED37
Интерфейс по умолчанию: ICaptchaRecognizer
GUID интерфейса: DB885F9B-44B1-4AE4-9AE8-7BD92563611D


ЗАМЕЧАНИЕ: Для того что бы использовать CaptchaServices.dll как COM объект его
нужно зарегистрировать в системе командой regsvr32 следующим образом:
regsvr32.exe CaptchaServices.dll

2.1. Свойство Login. Get/Put.
Имя пользователя в системе распознавания. Должно быть установлено до начала работы с
сервисом.

2.2. Свойство Passwd. Get/Put.
Пароль. Должен быть установлен до начала работы с сервисом.

2.3. Init(string bstrLogin, string bstrPasswd)
Функция дублирующая функционал свойств 2.1 и 2.2.

2.4. RecognizeFromFile
Функция распознавания изображения из файла.

[C++] HRESULT RecognizeFromFile([in] BSTR bstrFileName, [out,retval] BSTR* bstrText)
[JScript] string RecognizeFromFile(string FileName)

Функция принимает в качестве входного параметра имя файла с изображением, а возвращает
распознанный текст. Если функция вернула пустую строку, то код ошибки находится с свойстве
LastError. Если результирующая строка не пустая, то идентификатор изображения находится в
свойстве LastId.

Для С++. В случае ошибки возвращаемое значение E_FAIL.

2.5. Report.
Функция рапортующая на сервер о правильности распознавания изображения.

[C++] HRESULT Report([in] long lId, [in] VARIANT_BOOL bRecognized)
[JScript] Report(Id, bRecognized)

В качестве параметров принимает идентификатор изображения возвращаемый функциями RecognizeFromFile
и RecognizeFromMem, а так же флаг истинности распознавания.

2.6. Свойство LastError. Get.
Свойство содержащее код ошибки последнего распознавания. Только на чтение.

2.7. Свойство LastId. Get.
Свойство содержащее идентификатор последнего распознанного изображения. Только на чтение.

Пример на С++
Код:
// CaptchaServicesTest.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include <crtdbg.h>
#include <stdio.h>
#include "CaptchaServicesTest.h"
#include "..\..\CaptchaServices.h"

#define USERNAME "system_key"
#define PASSWORD "Your System Key" 

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	Init(USERNAME, PASSWORD);
    LPSTR pszText = NULL;
    long idErr = 0;
    int id = RecognizeFromFile("example/pics/4.jpg", pszText, &idErr);

    char mmsg[200];
    if (id == 0)
    {
        sprintf(mmsg, "Error: %d", idErr);
        MessageBox(NULL, mmsg, "Error", MB_OK);
    }
    else
    {
        sprintf(mmsg, "Text: %s", pszText);
        bool bRec = false;
        Free(pszText);
        if (MessageBox(NULL, mmsg, "Is text right?", MB_YESNO) == IDYES)
        {
            bRec = true;
        }
        
        Report(id, bRec);   
    }

	double balance = GetBalance(&idErr);
	if (idErr != 0)
    {
        sprintf(mmsg, "Error: %d", idErr);
        MessageBox(NULL, mmsg, "Balance error", MB_OK);
    }
	else
	{
        sprintf(mmsg, "Balance is $%lg", balance);
		MessageBox(NULL, mmsg, "Balance", MB_OK);
	}

	double nLimit = 0, nLimitUsed = 0;
	GetLimits(&nLimit, &nLimitUsed, &idErr);
	if (idErr != 0)
    {
        sprintf(mmsg, "Error: %d", idErr);
        MessageBox(NULL, mmsg, "Limits error", MB_OK);
    }
	else
	{
        sprintf(mmsg, "Used %lg of %lg", nLimitUsed, nLimit);
		MessageBox(NULL, mmsg, "Limits", MB_OK);
	}

    return TRUE;
}

Пример модуля для Delphi с прототипами функций.
Позволяет без затрат импортировать функции.
Код:
	(* Created by TaveL  2008 *)
	unit CaptchaServices;

	interface

	const
   	  Lib = 'CaptchaServices.dll'; // DLL должна находится в папке с программой

	procedure Init(Login, Password: PChar); stdcall; external Lib name 'Init';
	function RecognizeFromFile(FileName: PChar; var Text: PChar; Error: PInteger): Integer; stdcall; external Lib name 'RecognizeFromFile';
	function RecognizeFromMem(ImageBuf: PByte; BufSuze: LongWord; var Text: PChar; Error: PInteger): Integer; stdcall; external Lib name 'RecognizeFromMem';
	procedure Report(ID: Integer; Recognized: Boolean); stdcall; external Lib name 'Report';
	procedure Free(Text: PChar); stdcall; external Lib name 'Free';

	implementation

	end.

Вот полностью исходники и куча примеров по этой dll http://captchabot.com/download/win.zip

Помогите пожалуйста разобраться ...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
o_nix [?]
$otvet_dll = DllStructCreate("str ident;long errore")

"str" - такого типа в AutoIt нет, размер строки ты должен определить однозначно. Например:

Код:
$otvet_dll = DllStructCreate("char ident[1024];long errore")


или

Код:
$otvet_dll = DllStructCreate("char[1024];long")




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

Код:
$Dll = DllOpen('CaptchaServices.dll')

$Result = DllCall($Dll, 'int', 'Init', 'str', 'login','str', 'password')

$tData = DllStructCreate('char[1024]')
$Result = DllCall($Dll, 'int', 'RecognizeFromFile', 'str', 'captcha.jpg', 'ptr', DllStructGetPtr($tData), 'long*', 0)
If (@error) Or ($Result[0] = 0) Then
	If @error Then
		MsgBox(16, 'Ошибка вызова', @error)
	Else
		MsgBox(16, 'Ошибка распознавания', $Result[3])
	EndIf
Else
	MsgBox(64, 'ID капчи', $Result[0])
EndIf

DllClose($Dll)
 
Автор
O

o_nix

Новичок
Сообщения
35
Репутация
1
Спасибо скрипт работает ... вижу что я очень очень сильно всё усложнял ...
Попробую прокомментировать участки кода в которых у меня есть сомнения, дабы убедиться что я правильно понял все моменты и разъяснить некоторые непонятки - невпоследний раз dll подключаю - очень очень хочется разобраться...

Код:
$Dll = DllOpen('CaptchaServices.dll')

$Result = DllCall($Dll, 'int', 'Init', 'str', 'login','str', 'password')

$tData = DllStructCreate('char[1024]') 
;Тоесть создаётся  структура содержащая ровно 1024 байта ?? Тоесть нам абсолютно всёравно что
; там выдаёт dll в ответ и в каких типах?. И абсолютно неважно какая dll - всегда и с любой можно 
;будет задать только один тип char[1024] - для любых выводимых параметров ??

; Мы выделяем ей 1024 байта в которые она поместит весь свой вывод. (исходя из чего выбирается
; размерность ?? Нужно указать произвольное НЕменьшее колличество дабы весь вывод функции
; туда поместился (имеется ли тут требование к "байтности" ?? тоесть это должны быть цифры из 
;ряда "8 16 32 256 1024 и тд" ... или это неважно ??) или это должна быть точная величина 
;соответствуящая размеру вывода функции ?? Как тогда её определить ??

; При этом каждый указанный при DllCall тип данных будет в этой структуре автоматически выведен 
;"на отдельную строку" - тоесть это можно сравнить с получением некоего многострочного текста в 
;котором каждый тип данных находится на отдельной строке ? При этом весь этот текст записывается в память
;Начиная с адреса DllStructGetPtr($tData) и кончаяя концом выведенных данных ? :D 
;Либоже мы здесь создали структуру для получения только лишь ID капчи а возвращаемая ошибка нам неинтересна ??


$Result = DllCall($Dll, 'int', 'RecognizeFromFile', 'str', 'captcha.jpg', 'ptr', DllStructGetPtr($tData), 'long*', 0)
;Тут тоже в основном всё понятно но указан тип "str - строка" - это из AutoIT_help_rus
; - тоесть нельзя создавать в структуре такой тип тк он безразмерный ?? но потом можно указывать его при вызове функции поскольку мы даём ей строку конкретного конечного размера?

; Осталась непонятка с типом 'long*' - что конкретно означает звёздочка ??

; Плюс непонятно 'long*', 0) - этот Нуль - это значение переменной поумолчанию - тоесть после
; работы функции он поменяется на выданное ?? И если его просто неуказать при вызове функции то
; функция несработает ?? тоесть это важный для этой конкретной вызываемой функции параметр ??
; Или мы сразу говорим функции что невыводи ты нам код ошибки он нам ненужен - мы даже под него в
; структуре места невыделили ???

If (@error) Or ($Result[0] = 0) Then
    If @error Then
        MsgBox(16, 'Ошибка вызова', @error)
    Else
        MsgBox(16, 'Ошибка распознавания', $Result[3])
    EndIf
Else
    MsgBox(64, 'ID капчи', $Result[0])

; Искомая величина в структуре находится на первой строке ??
; И ещё возникает вопрос структура - она "сразу мгновенно получаемый многострочный ответ 
;содержащий все параметры всех типов" ?? Нам остаётся всеголиш выбрать нужную строку ??
; Или она последовательно выдаёт несколько строк а мы лиш дожидаемся пока будет выведена
; строка указанная нами ??
EndIf

DllClose($Dll)


И ещё один вопрос как можно вывести в консоль сразу все данные находящиеся структуре в текстовом виде ?? Чтобы определить каторая "строка" по счёту нам нужный параметр ? Можноли както это сделать или только перебором $Result[0] - $Result[N] ??

Огромное СПАСИБО за помощь :smile:
 
Верх