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

Передача данных из C++ DLL в Delphi: решение проблемы с указателями

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

Передача данных из динамически подключаемой библиотеки (DLL), написанной на C++, в программу на Delphi может быть непростой задачей, особенно когда речь идет о передаче указателей на данные. В данном случае рассматривается ситуация, когда необходимо сохранить данные в DLL и передать в Delphi программу ссылку на эти данные и их размер.

Проблема

Разработчик столкнулся с проблемой, при которой не удавалось получить доступ к данным, передаваемым из C++ DLL в Delphi программу. В C++ DLL была реализована функция, которая должна была вернуть ссылку на строку и её длину. Однако, в Delphi коде, который явно загружал DLL и вызывал эту функцию, данные не были доступны.

Исходный код

Код C++ DLL функции выглядел следующим образом:

void __stdcall exportClass::getDataReference(char* data, int* bufferLength)
{
    charArray = "Pass this Array of Char By Reference";
    data = charArray;
    bufferLength = sizeof(charArray) / sizeof(charArray[0]);
}

В Delphi коде для вызова функции был использован следующий подход:

procedure callDllFunction();
var
  dynamicCharArray : array of AnsiChar;
  pData: PAnsiChar;
  length: Integer;
  pInt: ^Integer;
begin
  pData := @dynamicCharArray[0];
  length := 10;
  pInt := @length;
  explicitDllLoaderClass.callGetDataReference(pData, pInt);
  SetLength(dynamicCharArray, length);
end;

Анализ проблемы

В приведенном коде есть несколько ошибок:

  1. В C++ коде параметр data передается по значению, что означает, что изменения, внесенные в этой переменной внутри функции, не будут доступны вызывающему коду. Необходимо передать параметр по ссылке или указателю.

  2. В C++ коде используется sizeof(charArray) для определения длины строки, что некорректно, так как sizeof возвращает размер массива в памяти, а не фактическую длину строки.

  3. В Delphi коде массив dynamicCharArray выделяется после вызова функции, что приводит к потере данных.

  4. В Delphi коде не учитывается, что C++ функция является методом класса, и не создается объект класса для вызова этого метода.

Подтвержденное решение

Для корректной работы необходимо:

  • Передать параметры data и bufferLength по ссылке в C++ функции.
  • В C++ коде использовать функцию strlen для определения длины строки.
  • В Delphi коде выделить память для массива перед вызовом функции.
  • В Delphi коде учитывать, что C++ функция является методом класса, и создать объект класса для вызова этого метода.

Альтернативное решение

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

Пример C++ кода для DLL:

BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

extern "C" __declspec(dllexport) void __stdcall getDataReference(char* data, int* bufferLength)
{
    char charArray[] = "Pass this Array of Char By Reference";
    if ((data == NULL) || (bufferLength == NULL) || (*bufferLength <= 0))
        return;
    strncpy(data, charArray, *bufferLength);
    *bufferLength = strlen(charArray);
}

Пример Delphi кода для использования DLL:

program CallMyDll;
{$APPTYPE CONSOLE}
{$R *.res}
uses
  Winapi.Windows,
  System.SysUtils;
type
    TGetDataReference = procedure (var Data: PAnsiChar; var BufferLength: PInteger); stdcall;
var
    DllHandle: THandle;
    GetDataReference: TGetDataReference;
    ...
begin
    ...
    GetDataReference := GetProcAddress(DllHandle, '_getDataReference@8');
    ...
    procedure callDllFunction();
    var
        DynamicCharArray: array of AnsiChar;
        DataLength: Integer;
        S: String;
    begin
        DataLength := 1000;
        SetLength(DynamicCharArray, DataLength);
        GetDataReference(PAnsiChar(DynamicCharArray), @DataLength);
        SetLength(DynamicCharArray, DataLength);
        S := String(PAnsiChar(DynamicCharArray));
        WriteLn(S);
    end;
end.

Заключение

При передаче данных из C++ DLL в Delphi программу важно учитывать особенности работы с указателями и передачу параметров по ссылке. Обеспечение корректной работы с памятью и использование правильных функций для работы со строками позволит избежать типичных ошибок и успешно решить поставленную задачу.

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

Разработчик сталкивается с трудностями при передаче данных из динамически подключаемой библиотеки (DLL), написанной на C++, в программу на Delphi, особенно с передачей указателей на данные и их размер.


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

Получайте свежие новости и обновления по 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-02-05 10:49:20/0.0036690235137939/0