Вопрос пользователя связан с передачей массива вещественных чисел из C++ DLL в программу на Delphi. При тестировании DLL в консольном приложении на C++ результат работы был корректным, но при попытке использовать ту же DLL в Delphi, содержимое возвращаемого массива оказывалось неверным.
Пример кода на C++:
#define DllExport __declspec( dllexport )
extern "C"
{
DllExport double* SomeMethod(double level)
{
double* array = new double[2]; // Пример: массив из двух элементов
array[0] = 42.0;
array[1] = 666.0;
return array;
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_DETACH:
// Освобождение памяти для массива
delete [] array;
break;
}
return TRUE;
}
Пример кода на Delphi:
program ReturnDoubleFromDLL;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.WinTypes,
System.WinProc,
dlfcn;
type
TSomeMethod = function(level : Double): PDouble; cdecl;
var
SomeMethod: TSomeMethod;
arr: PDouble;
lib: Handle;
begin
lib := dlopen('path_to_your_dll.dll', RTLD_LAZY);
if not Assigned(lib) then
raise Exception.Create('Cannot load DLL');
SomeMethod := dlsym(lib, 'SomeMethod');
if not Assigned(SomeMethod) then
raise Exception.Create('Cannot find SomeMethod');
arr := SomeMethod(15.0);
try
// Работа с массивом
Writeln(arr^:3:0);
Inc(arr);
Writeln(arr^:3:0);
finally
// Освобождение памяти
delete[] arr;
end;
dlclose(lib);
Readln;
end.
Объяснение проблемы:
Проблема заключается в том, что C++ DLL выделяет память для массива double внутри функции SomeMethod, и этот массив удаляется при отсоединении DLL. В Delphi, при вызове этой функции, указатель на массив успешно передается, но после закрытия DLL, память освобождается, и указатель становится недействительным.
Подтвержденный ответ:
Для корректной работы с массивом double, возвращаемым из C++ DLL, необходимо использовать копию этого массива в Delphi. Это можно сделать, выделив память для нового массива в Delphi и скопировав в него данные из массива, полученного из DLL.
Альтернативный ответ:
Возможное решение проблемы — изменение дизайна DLL, чтобы она возвращала копию данных, а не указатель на выделяемую в динамической памяти память. В таком случае, в C++ функции SomeMethod можно было бы изменить так, чтобы она возвращала статический массив, или выделять память в стеке, а не в куче.
// В Delphi
var
arr: array of Double;
count: Integer;
begin
SetLength(arr, 2);
Move(SomeMethod(15), arr[0], SizeOf(Double) * 2); // Копирование данных
// Работа с массивом arr
end;
Заключение:
При работе с C++ DLL и Delphi важно понимать, как управлять памятью и копировать данные между языками. В данном случае, проблема заключалась в некорректном управлении памятью и необходимости копирования данных из возвращаемого DLL массива.
Проблема связана с передачей массива вещественных чисел из C++ DLL в программу на Delphi, где при попытке использования DLL в Delphi содержимое возвращаемого массива оказывается неверным из-за освобождения памяти в DLL, что делает указатель недействитель
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.