Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Особенности работы с памятью в DLL на Delphi 2007 для приложений на Visual Basic 6 и Visual Basic 2010

Delphi , Файловая система , DLL и PlugIns

Вопрос, поставленный пользователем, касается взаимодействия между библиотекой, созданной в среде Delphi 2007, и приложениями на Visual Basic 6 и Visual Basic 2010. Основная проблема заключается в передаче строковых данных из Delphi DLL в Visual Basic приложение и освобождении памяти, выделенной через функцию GetMem в Delphi.

Описание проблемы

В коде Visual Basic используется декларация функции из DLL:

Declare Function TstCharReturn Lib "myLib" Alias "TstCharReturn" (ByVal c As System.Text.StringBuilder) As Boolean

И вызов этой функции:

Private Sub Button1_Click(ByVal sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim s As String
    Dim builder As New System.Text.StringBuilder
    Dim r As Boolean
    r = TstCharReturn(builder)
    LogIt(s) ' Предполагается, что строка из builder должна быть передана сюда'
    LogIt(r)
End Sub

Автор вопроса получил рекомендацию использовать System.Text.StringBuilder вместо String, так как строки в .NET не изменяемы, но обе структуры данных работают аналогично.

В коде Delphi DLL функция выглядит так:

Function TstCharReturn(var c: pChar): Boolean; stdcall;
var
    BuffSize: Integer;
    sOut: string;
begin
    sOut:='abcdefghijklmnoprst';
    BuffSize:=SizeOf(Char) * (Length(sOut) + 1);
    GetMem(c, BuffSize);
    FillChar(c^, BuffSize, 0);
    Result := Length(sOut) > 0;
    if Result then
    begin
        Move(sOut[1], PChar(c)^, BuffSize);
    end;
end;

Автор вопроса получает "мусор" в выводе Visual Basic. Он также задает вопрос о необходимости освобождения памяти, выделенной функцией GetMem, и о различиях между Visual Basic 6 и 2010, поскольку DLL должна работать с обоими версиями.

Подтвержденный ответ

Проблема заключается в неправильной реализации функции TstCharReturn в Delphi. Вместо выделения новой памяти для возвращаемой строки, необходимо использовать уже существующий буфер, переданный в параметре c. Также необходимо передать размер этого буфера в качестве дополнительного параметра функции.

Исправленный код Visual Basic будет выглядеть так:

Declare Function TstCharReturn Lib "myLib" Alias "TstCharReturn" _
    (ByVal c As System.Text.StringBuilder, ByVal cchSize As Integer) As Boolean

И вызов функции с указанием начальной емкости буфера:

Dim sb As New System.Text.StringBuilder(50) ' Начальная емкость буфера: 50
TstCharReturn(sb, sb.Capacity)

Код Delphi также должен быть изменен:

Function TstCharReturn(const c: pChar; cchSize: Integer): Boolean; stdcall;
var
    sOut: string;
begin
    sOut:='abcdefghijklmnoprst';
    if Length(sOut) <= cchSize then
    begin
        Move(sOut[1], c, Length(sOut));
        Result := True;
    end
    else
    begin
        Result := False;
    end;
end;

Альтернативный ответ

При вызове неmanaged кода из .NET, StringBuilder не будет автоматически передан как буфер, способный принять произвольное количество данных. Необходимо убедиться, что начальная емкость буфера достаточна для возвращаемых данных.

Также, в Delphi процедуре с var ожидается указатель на указатель на char, а в декларации Visual Basic — указатель на char. Удаление var из объявления функции в Delphi позволяет процедуре ожидать указатель на char. Это изменение позволяет записывать данные в область памяти, на которую указывает c.

При использовании P/Invoke важно явно указать, что StringBuilder должен быть маршалирован как ANSI, а не Unicode, используя атрибут MarshalAs(UnmanagedType.LPStr) или установив свойство Charset декларации DLL в Charset.Ansi.

По умолчанию P/Invoke использует ANSI кодировку для строковых параметров, но это может быть платформо-зависимо, поэтому следует быть внимательным при работе с кросс-платформенными вызовами.

Комментарии

  • Пользователь отмечает, что после внесения рекомендуемых изменений код работает корректно, но остается вопрос о причинах возникновения проблемы и ресурсах для более глубокого понимания работы с указателями и памятью.
  • Рекомендуется обратиться к ресурсам, посвященным работе с указателями в C++ для лучшего понимания этих концепций.

Заключение

Работа с памятью в DLL на Delphi 2007 для приложений на Visual Basic 6 и Visual Basic 2010 требует особого внимания к деталям, таким как управление памятью, передача строковых данных и правильное использование указателей. Следуя рекомендациям и правильно настроив взаимодействие между языками и средами, можно добиться корректной работы кроссплатформенных приложений.

Создано по материалам из источника по ссылке.

Вопрос связан с передачей строковых данных из библиотеки, созданной в среде Delphi 2007, в приложения на Visual Basic 6 и Visual Basic 2010, с особым вниманием к управлению памятью и использованию указателей.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: DLL и PlugIns ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-16 19:16:09/0.0036640167236328/0