Вопрос создания и использования динамических библиотек в среде разработки Delphi может показаться сложным на первый взгляд, особенно для начинающих разработчиков. Однако, следуя инструкциям и учитывая некоторые важные моменты, можно успешно решить поставленные задачи.
Описание проблемы
Пользователь столкнулся с проблемой при попытке чтения переменной versione из динамической библиотеки (DLL) в среде Delphi. Проблема заключалась в возникновении ошибки "Invalid Pointer Operation" при вызове функции Versione, экспортируемой из DLL. Это произошло после того, как пользователь следовал инструкциям по созданию DLL, найденным на сайте Tutorialspoint.
Контекст проблемы
В коде DLL пользователь определил функцию Versione, которая принимает два параметра: строку messaggio и строку versione. Если messaggio содержит строку 'chiama', то функция устанавливает versione в значение 'v4.0.0 build 31'. В главном приложении пользователь также определил функцию Versione с аналогичными параметрами, используя внешнюю ссылку на функцию из DLL.
Подтвержденный ответ
Проблема, с которой столкнулся пользователь, связана с неправильной передачей строковых параметров между приложением и DLL. В комментариях к коду, сгенерированных IDE при создании DLL, указано, что для избежания использования дополнительной библиотеки BORLNDMM.DLL следует передавать строковую информацию с использованием параметров типов PChar или ShortString.
Альтернативный ответ
Для корректной работы с DLL необходимо использовать параметры типа PChar или ShortString для передачи строковых данных. Это связано с тем, что использование типов String в функциях, экспортируемых из DLL, делает их несовместимыми с вызовами из других языков, например, из C. Также важно, чтобы вызывающее приложение предоставляло память для результата и указывало ее длину.
Пример кода
Ниже представлен пример кода динамической библиотеки SimpleTest с функцией TestDLL, которая принимает строку arg, буфер Buffer для результата и его длину Len. В примере используется PChar для передачи строковых параметров:
library SimpleTest;
uses
SysUtils,
Classes;
{$R *.res}
// Parameters:
// arg: Argument, указывающий, является ли это тестом или чем-то еще
// таким образом, мы знаем, какой возвращать значение
// Buffer: Пространство, в котором разместить результат
// Len: Длина предоставленного буфера
function TestDLL(const arg: PChar; const Buffer: PChar; const Len: Integer): Boolean; stdcall;
begin
// Убедитесь, что мы используем параметр Len, чтобы не переполнить
// предоставленное нам пространство памяти. StrLCopy скопирует максимум
// Len символов, даже если длина предоставленной строки источника
// больше.
if arg = 'Test' then
StrLCopy(Buffer, 'Test result', Len)
else
StrLCopy(Buffer, 'Non-test result', Len);
Result := True;
end;
exports
TestDll;
begin
end.
В тестовом приложении, вызывающем TestDLL, также используется PChar для передачи строки Parm2 в качестве буфера для результата:
unit DLLTestForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
function TestDLL(const arg: PChar; const Buffer: PChar; const Len: Integer): Boolean; stdcall;
external 'SimpleTest.dll';
procedure TForm4.Button1Click(Sender: TObject);
var
Parm1: String;
Parm2: String;
BuffLen: Integer;
begin
Parm1 := 'Test';
// Длина буфера (включая нулевой символ) для вызова DLL
// Выбрана произвольно - я знаю, что DLL не вернет более 15 + нулевого символа. Я притворяюсь, что не знаю, и оставляю дополнительное место. DLL не вернет более 30 символов, даже если у нее есть что сказать, потому что она использует StrLCopy, чтобы ограничить результат значением Len символов.
BuffLen := 30;
// Выделение памяти для возвращаемого значения
SetLength(Parm2, BuffLen);
// Вызов DLL с аргументом `Test`
if TestDLL(PChar(Parm1), PChar(Parm2), BuffLen) then
ShowMessage(Parm2);
// Вызов DLL с другим значением параметра
Parm1 := 'Other';
if TestDLL(PChar(Parm1), PChar(Parm2), BuffLen) then
ShowMessage(Parm2);
end;
end.
Заключение
Использование динамических библиотек в Delphi требует внимательного отношения к передаче строковых параметров и правильной организации памяти для результатов. Следуя рекомендациям по использованию PChar или ShortString, можно избежать ошибок, связанных с неверной операцией с указателями.
Проблема пользователя заключается в неправильной передаче строковых параметров между приложением Delphi и динамической библиотекой, что привело к ошибке 'Invalid Pointer Operation' при попытке чтения значения переменной из DLL.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.