1

Тема: AHK: Как передать строку в DllCall по ссылке и получить строку назад

Есть переменная со строкой, ее нужно передать внутрь функции из DLL библиотеки и назад из этой же DLL нужно получить строку. Передачу желательно делать по ссылке, но если это сложно то можно просто передать саму строку.

Исходная строка что передали внутрь DLL приходит какая-то кривая, при вызове MessageBox из DLL выводится белеберда.
Результат что возвращает DLL значение 8 - это длина строки, она верная, ErrorLevel = 0 - значит все отработало нормально, но вот значение StrOut после вызова пустое, там ничего нет.

Помогите разобрать что нужно поправить чтобы все заработало, чтобы строка принималась и записывалась в StrOut .

код AutoHotkey:


; ---- исходные данные ----
StrIn := "AbCdEfGh"        ; исходная строка которую нужно передать в DLL функцию
ptr_StrIn := &StrIn        ; указатель на строку StrIn
VarSetCapacity(StrOut, 20) ; переменная куда поместим результат после вызова DLL, для нее зарезервировали 20 байт
ptr_StrOut := &StrOut      ; указатель на строку StrOut

Result := DllCall("test.dll\testfunc", StrP, ptr_StrIn,  UInt64, StrLen(StrIn),  StrP, ptr_StrOut, "CDecl")

MsgBox, DLL вернула значение: %Result% , ErrorLevel: %ErrorLevel% , значение StrOut после вызова: %StrOut%

код функции в DLL (test.c - исходник на C++):


#include <Windows.h> // для MessageBox()

long int testfunc(const unsigned char *in, unsigned long long int inLen, unsigned char *out)
{
    char str[20] = "";
    for(unsigned long long int i = 0; i < inLen; i++)
    {
        out[i] = in[i];
        str[i] = in[i];
    }
    MessageBox(NULL, str, "String In", MB_OK);
    return inLen;
}

2

Re: AHK: Как передать строку в DllCall по ссылке и получить строку назад


; ---- исходные данные ----
StrIn := "AbCdEfGh"        ; исходная строка которую нужно передать в DLL функцию
ptr_StrIn := &StrIn        ; указатель на строку StrIn
VarSetCapacity(StrOut, 20) ; переменная куда поместим результат после вызова DLL, для нее зарезервировали 20 байт
ptr_StrOut := &StrOut      ; указатель на строку StrOut

Result := DllCall("test.dll\testfunc", "astr", StrIn,  UInt64, StrLen(StrIn),  "ptr", ptr_StrOut, "CDecl")

OutText := StrGet(ptr_StrOut, Result, "cp0")

MsgBox, DLL вернула значение: %Result% , ErrorLevel: %ErrorLevel% , значение StrOut после вызова: %OutText%

3

Re: AHK: Как передать строку в DllCall по ссылке и получить строку назад

YMP Спасибо, код заработал.

4

Re: AHK: Как передать строку в DllCall по ссылке и получить строку назад

YMP Есть мини проблема, код работает пока в выходном потоке в переменной StrOut нет символа с кодом 00:HEX (это нулевой символ). Вот пример в HEX:
33 dc 44 21 00 33 1b 35 - так должно быть
33 dc 44 21                     - так получается (обрывается на нулевом символе)

Менять кодировку с "cp0" на что-то другое результата не дает.
Как сделать чтобы все символы записались в StrOut и даже нулевой?

5

Re: AHK: Как передать строку в DllCall по ссылке и получить строку назад

Ну, вообще-то 0 — это конец строки. Так что всё законно. Поэтому уточните, речь о строке или о нескольких строках?

6

Re: AHK: Как передать строку в DllCall по ссылке и получить строку назад

YMP речь об одной строке которую возвращает функция из DLL.
Алгоритм следующий есть исходная строка StrIn ее и ее длину StrLen(StrIn) передаем в функцию из DLL, назад получаем ХЭШ этой строки в переменную StrOut, также функция из DLL вернет длину этой ХЭШ строки в переменную Result.

В переменной StrOut могут быть произвольные символы в том числе и 00:HEX.

Я реализую алгоритм подсчета SHA-3 https://ru.wikipedia.org/wiki/SHA-3
мне внутри переменной StrOut нужна ХЭШ сумма.

Как мне получить полностью эту ХЭШ сумму?

7

Re: AHK: Как передать строку в DllCall по ссылке и получить строку назад

Она там и будет. Но MsgBox не воспроизведёт то, что идёт после 0.

8

Re: AHK: Как передать строку в DllCall по ссылке и получить строку назад

YMP ее там нет, длина  ХЭШ суммы StrLen(OutText) меньше чем Result.

Что бы она там появиласть пришлось поменять одну строку присвоения значения, убрала  "CP0":

OutText := StrGet(ptr_StrOut, Result)

Спасибо за помощь

9

Re: AHK: Как передать строку в DllCall по ссылке и получить строку назад

StrLen тоже только до 0 меряет. Так что всё там есть. А убрав "cp0", вы поменяли кодировку чтения на Юникод, и этот нулевой байт стал восприниматься как часть кода символа. Т.е. строка у вас в кодировке ANSI, а вы её читаете как юникодную. Короче, петрушка получается. Если из DLL выдаётся не осмысленный текст, а набор байтов, то проще с ним работать в переменной StrOut, нет смысла его читать в другую.