Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 2 663

Раздел: Delphi » Прочее
/ вопрос открыт /

Доброго времени суток, уважаемые эксперты!

Помогите разрешить следующую проблему.

Есть уже разработанная на С++ DDL библиотека доступа к спец. железу.
Необходимо использовать экспортированные из нее функции в приложение написанном на Delphi.
С самим экспортом проблем нет (делается штатно - либо статически либо динамически с соответствующим приведением типов). Проблема в том, что некоторые функции этой библиотеки используют захват памяти на своей стороне с помощью сишной функции CoTaskMemAlloc(...), а освобождаться захваченная память должна на стороне пользователя (т.е. в Delpfi приложении) которое эту библиотеку будет использует.

например для функции GetDevices(...) из C++ DLL библиотеки:

EXTERN_C __declspec( dllexport ) int GetDevices(unsigned __int64 ** devices, int *count)
{
int r = start();
if(r != 0)
{
return 3;
}
unsigned __int64 * DEVICES = NULL;
if (m_count > 0);
{
DEVICES = (unsigned __int64 *)CoTaskMemAlloc(sizeof(unsigned __int64) * m_count);
for (int i = 0; i < m_count; i++)
{
DEVICES[i] = dev[i].addr;
}
}
*devices = DEVICES;
*count = m_count;
return 0;
}


В вызывающем приложении на С# это делается легко и будет выглядеть так:
...
ulong megaADDR = 0;
...
unsafe
{
int count = 0;

IntPtr ptr = IntPtr.Zero;
GetDevices(ref ptr, out count);

ulong* p = (ulong*)ptr.ToPointer();

if (count > 0)
{
megaADDR = ((ulong*)ptr.ToPointer())[0]; // Или другой какой нибуть индекс по массиву
}

Marshal.FreeCoTaskMem(ptr);
}
...

А как тоже самое сделать в приложении написанном на Delphi ???
Заодно подскажите как указатель на указатель в Delpfi лучше оформить для сишной функции GetDevices(unsigned __int64 ** devices, int *count) из DLL?

VictorK Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: VictorK (статус: Посетитель)
Вопрос отправлен: 19 апреля 2009, 20:22
Состояние вопроса: открыт, ответов: 0.


Мини-форум вопроса

Всего сообщений: 8; последнее сообщение — 22 апреля 2009, 19:18; участников в обсуждении: 3.
Death_Master

Death_Master (статус: Посетитель), 19 апреля 2009, 22:03 [#1]:

А может ли сама dll обладать функциями освобождения памяти?
Если да, то их можно просто импортировать и вызывать по необходимости...
Обычно захожу по ночам... (60-70%)
Если нужно что-то написать, то беру оборудованием, деньгими и пивом(при личной встрече)...
P.S. Помогаю и рассказываю бесплатно ^_^.....Nyaaa!
VictorK

VictorK (статус: Посетитель), 19 апреля 2009, 22:18 [#2]:

Увы, DLL уже разработана и используется давно и многими, т.е. "Отлита в бронзе" и изменению не подлежит.
Заказчик заказывает музыку. Можно либо сделать либо отказаться.
Death_Master

Death_Master (статус: Посетитель), 19 апреля 2009, 22:22 [#3]:

В таком случае можно сделать дополнительную dll:
прога -> dll- обёртка( с функциями работы с памятью) -> исходная dll
в такой конфигурации будут все необходимые функции :)
Обычно захожу по ночам... (60-70%)
Если нужно что-то написать, то беру оборудованием, деньгими и пивом(при личной встрече)...
P.S. Помогаю и рассказываю бесплатно ^_^.....Nyaaa!
VictorK

VictorK (статус: Посетитель), 19 апреля 2009, 22:43 [#4]:

Спасибо за идею Death Master.
Конечно как крайний вариант доп. Dll-обертка подойдет, но хотелось бы сделать это более естественно как в C#.
Уж больно много там подобных функций, разбираться переписывать довольно накладно будет.
Вадим К

Вадим К (статус: Академик), 20 апреля 2009, 21:47 [#5]:

А почему просто не взять и не написать это прям так на делфи?
например
(ulong*)ptr.ToPointer();
это будет
PLongInt(@prt);
Что бы сделать массивы, надо просто привести к нужному типу, например есть PByteArray для байтового. правда так как это массив, то надо будет ещё крышечку, то есть где то
(PByteArray(prt)^)[0]
Галочка "подтверждения прочтения" - вселенское зло.
VictorK

VictorK (статус: Посетитель), 22 апреля 2009, 05:16 [#6]:

Спасибо всем за подсказки.

С передачей указателя на указатель массива получилось сделать так:

....

// Получение списка устройств
//EXTERN_C __declspec( dllexport ) int GetDevices(unsigned __int64 ** devices, int *count);
type
PUInt64Array = ^TUInt64Array;
TUInt64Array = array[0..(MaxInt div 16) - 1] of UInt64;
function GetDevices(var pdevices: pointer; var Count:integer):integer; cdecl; external RPTDev_DRVDllName name 'GetDevices';

...

var
ppDevs: Pointer; Count: integer;
i : integer; DevArray: array of UInt64;

...

Count:= 0; ppDevs:= nil;
GetDevices(ppDevs, Count);

if Count <> 0 then
begin
SetLength(DevArray, Count);
for i := 0 to Count-1 do
begin
DevArray[i] := (PUInt64Array(ppDevs)^)[i];
end;
end;


А вот с освобождением памяти, попробовал использовать
CoTaskMemFree(ptr); из
uses Ole2;
и получил кучу конфликтов имен при компиляции.

Наверное придется либо писать свою Dll-библиотеку, либо уламывать сделать функции вызов освобождения памяти в самой Dll-библиотеке, что-то типа вот так:

В DLL-библиотеке
// Освобождение памяти массива списока устройств
EXTERN_C __declspec( dllexport ) int FreeDevices(unsigned __int64* devices)
{
CoTaskMemFree(devices);
return 0;
}


В Delphi - приложении
...
// Освобождение памяти массива списока устройств
function FreeDevices(var pdevices: PUInt64):integer; cdecl; external RPTDev_DRVDllName name 'FreeDevices';

...

FreeDevices(PUInt64(ppDevs^));
Вадим К

Вадим К (статус: Академик), 22 апреля 2009, 09:02 [#7]:

По правилам, память должен освобождать тот, кто её выделил. В противном случае возможна куча проблем.
В вторых, освобождать память надо "парной функцией", а не какой попало, что Вы делаете.
Галочка "подтверждения прочтения" - вселенское зло.
VictorK

VictorK (статус: Посетитель), 22 апреля 2009, 19:18 [#8]:

Согласен, память надо освобождать корректно.
Увы эта DLL-ка не мое творение, хотелось оставить все как есть.
Буду просить хозяина DLL-библиотеки добавить парные функции освобождения памяти либо перепишу эту библиотеку сам и как надо.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:50
Выполнено за 0.03 сек.