works:programmer:delphi:pchar-for-dlls
Передача строк в библиотеку dll, и получение результата в Delphi
Знаю очень многие топорничают при работе со строками в Delphi, вот решил выложить пример как на всамом деле передаються PChar между библиотекой .dll и исполняемым файлом .exe
Код самой библиотеки :
library Project1; {$R *.res} uses System.SysUtils, System.Classes, Winapi.Windows; // Паскальная версия функция, то с чем обычно работаем. function HelloWorldP(Param1: string): string; begin if Param1 = 'hello' then Result := 'Hello World!' else Result := 'Say `hello` for me!'; end; // WinAPI Exports PWideСhar версия функци function HelloWorldW(Param1: PWideChar; lpBuffer: PWideChar; nSize: Integer): Integer; stdcall; var sBuffer : string; iBuffSz : Integer; iCopySz : Integer; begin sBuffer := HelloWorldP(StrPas(Param1)); // Получаем строку iBuffSz := Length(sBuffer) * sizeof(Char); // Получаем длинну строки if nSize < iBuffSz then iCopySz := iBuffSz // Если размера буффера хватает, то всё суппер копируем всю строку else iCopySz := iBuffSz; // Если не хватает, то копируем не более чем длинна буффера try CopyMemory(lpBuffer, PWideChar(sBuffer), iCopySz); // Копируем в буффер, из строки, байт Result := iBuffSz; // Результат, реальная длинна строки которую залили в буффер except Result := -1; // Обезательно обрабатываем ошибки, например буффера не было, а nSize дали end; end; exports // Таблица экспортов HelloWorldW name 'HelloWorldW'; begin {-} end.
А теперь код маленькой программки которая вызывает этот код:
program Project2; {$R *.res} uses System.SysUtils, Winapi.Windows; const DLL_FILE_PATH = 'project1.dll'; function HelloWorldW(Param1: PWideChar; lpBuffer: PWideChar; nSize: Integer): Integer; stdcall; external DLL_FILE_PATH name 'HelloWorldW'; var sDllQuestion : WideString; lpBuffer : PWideChar; nBufferSz : Integer; nRetnSz : Integer; sLibrarySays : WideString; begin // Спрашиваем сказать привет `hello`? if MessageBox(0, 'Say `hello` for dll?', 'Hello dll test', MB_ICONQUESTION or MB_YESNO ) = ID_YES then sDllQuestion := 'hello' else sDllQuestion := 'i have no question'; nBufferSz := 1024; // Размер буффера 1024 байта lpBuffer := AllocMem(nBufferSz); // Занять у Windows 1024 пайта памяти try // Сделать запрос // Параметр 1 : Сам возпрос // Параметр 2 : Выделенная у нас память // Параметр 3 : Сколько памяти для помещения строки nRetnSz := HelloWorldW(PWideChar(sDllQuestion), lpBuffer, nBufferSz); // Если результат -1, то произошла херня if nRetnSz = -1 then raise Exception.Create('Something wrong with params for dll') // Если размера буффера не хватило else if nRetnSz > nBufferSz then begin FreeMem(lpBuffer, nBufferSz); // Освобождаем память nBufferSz := nRetnSz + 2; // Берём длинну строки + 1 Буква (sizeof(WideChar) == 2) lpBuffer := AllocMem(nBufferSz); // Заготавливаем буффер // Второй раз спрашиваем у dll строку, но размер буффера мы уже увеличили до длинна_строки + 1 буква nRetnSz := HelloWorldW( PWideChar(sDllQuestion), lpBuffer, nBufferSz); end; // Всё окей, получили строку sLibrarySays := Copy(lpBuffer, 0, nRetnSz); // Выводим результат MessageBoxW(0, PWideChar(sLibrarySays), 'Response from dll', MB_ICONINFORMATION); finally FreeMem(lpBuffer, nBufferSz); // На забываем отдать Windows, память end; end.
Исходный код программки и библиотеки для Delphi XE2
works/programmer/delphi/pchar-for-dlls.txt · Последнее изменение: 2018/12/15 17:18 — 127.0.0.1