powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
25 сообщений из 87, страница 1 из 4
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39815407
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Возникла необходимость на Delphi написать DLL в которой функция должна возвращать массив записей типа :
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
TMyRecord = record
   Id: Integer;
   Name: string;
   DateCreate: TDateTime;
end;

TMyArray array of TMyRecord;

function MyFunc: TMyArray;



Пример предельно упрощенный,

Фишка в том, что эту DLL предполагается использовать из программ написанных на разных языках и средах, типа C++, PowerBuilder, Java, Delphi

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

У кого был такой опыт подскажите как тут быть, с какой стороны подойти...
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39815410
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker
Код: pascal
1.
2.
3.
4.
5.
TMyRecord = record
   Id: Integer;
   Name: pchar/pansichar/pwidechar;
   DateCreate: longint/int64; // unix-time
end;


Примерно так. Эти типы совместимы.

https://stackoverflow.com/questions/4420188/how-to-format-a-unix-timestamp-in-delphi
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39815431
ёёёёё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

не, нельзя управляемые типы (string, объекты).
Можно, если использовать COM(OLE), вебсервисы и проч.
Можно упаковывать в портабельные форматы (json, xml).
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39815437
ziv-2014
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,
Используй интерфейсы.
Строки передавай в widestring, pansichar, pchar, pwidechar.
Не используй управляемые типы.
Используй метод передачи параметров safecall или stdcall, cdecl (для java).
Не возвращай записи в результате функции. В функции возвращаешь результат работы функции или код ошибки.
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39815438
ziv-2014
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,
В какой DLL выделил память в той и удаляешь.
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39815444
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И делай структуры packed, чтобы не налететь на разницу в выравнивании. Либо явно задавай размер выравнивания
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39815446
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ziv-2014Используй интерфейсы.

Вовсе не обязательно. Большой оверхед во многих случаях
Не возвращай записи в результате функции. В функции возвращаешь результат работы функции или код ошибки.
Можно, но не обязательно
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39815529
ziv-2014
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Не возвращай записи в результате функции. В функции возвращаешь результат работы функции или код ошибки.
Можно, но не обязательно
Разные языки программирования по разному возвращают структуры, как результат функции.
С# и Delphi не совместимы и будет эксепшен.
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39815619
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

От managed-типов придётся отказаться, либо "выводить" функции для управления ими

К дельфи-специфичным типам вроде TDateTime тоже лучше не прибегать. Возьми аналоги, например Linux Time

С масивом всё просто, смотри похожие функции в WinAPI, там везде функция имеет два логичесикх варианта вызова: определение необходимого размера и собственно сама работа. Т.е. необходимую память выделяет вызывающая сторона.
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819368
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пытаюсь вернуть строку из DLL.
Пишу в таком духе:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
// процедура в DLL
procedure GetStringFromDLL(Buffer: LPWSTR; var dwSize: DWORD);
var
  OutStr: String;
begin
  OutStr := 'йцукен qwerty'; // как-то получили эту строку

  dwSize := Length(OutStr) * 2;

  if Buffer <> nil then
    Buffer := StrNew(PChar(OutStr));
end;



вот так пытаюсь ее прочитать из внешней программы:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
procedure ReadString;
var
  MyStr: String;
  Size: DWORD;
  Buffer: PChar;
begin
  Size := 0;

  GetStringFromDLL(nil, Size);

  if Size > 0 then
  begin
    Buffer := GetMemory(Size * 2);
    GetStringFromDLL(PChar(Buffer), Size);
    MyStr := PChar(Buffer);
    FreeMemory(Buffer);

    ShowMessage(MyStr);
  end;
end;


В MyStr в итоге оказывается мусор из иероглифов

В чем ошибка?
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819394
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,
зачем
Код: pascal
1.
GetMemory(Size * 2);


если
Код: pascal
1.
dwSize := Length(OutStr) * 2;
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819404
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrb,

Вы правы, промашка. Но это не решает проблему.
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819407
Александр Спелицин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-TalkerВ чем ошибка?
Например в том, что несколько вызовов PChar(Buffer) не гарантируют одного и того же результата.
Убирайте Ваш PChar() и передавайте уже саму переменную Buffer, как ссылку на выделенный участок памяти.
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819419
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker, а
Код: pascal
1.
Buffer: LPWSTR

и
Код: pascal
1.
Pchar(PChar)

одно и тоже?
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819421
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-TalkerВ чем ошибка?Во всем. Начиная с записи в пустоту
SQL-Talker
Код: pascal
1.
Buffer := StrNew(PChar(OutStr));


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
// процедура в DLL
function GetStringFromDLLW(Buffer: PWideChar; var dwSize: DWORD): Integer;
var
  OutStr: WideString;
  size: DWORD;
begin
  try
    OutStr := 'йцукен qwerty'; // как-то получили эту строку
    size := (Length(OutStr) + 1) * SizeOf(OutStr[1]);  // +1 for \0 symbol

    if size = 0 then
      Result := S_FALSE
    else if (Buffer = nil) or (dwSize < size) then
      Result := ERROR_NOT_ENOUGHT_MEMORY;
    else begin
      Move(OutStr[1], Buffer^, size);
      Result := S_OK;
    end;
    dwSize := size;
  except
    Result := E_FAIL;
  end;
end;

procedure ReadString;
var
  MyStr: String;
  Size: DWORD;
  Res: Integer;
begin
  Size := 0;
  MyStr := '';
  Res := GetStringFromDLLW(nil, Size);
  if Res = ERROR_NOT_ENOUGHT_MEMORY then begin
    SetLength(MyStr, (Size div SizeOf(WideChar)) - 1);
    Res := GetStringFromDLLW(PChar(MyStr), Size);
  end;
  if (Res = S_OK) or (Res = S_FALSE) then
    ShowMessage(MyStr)
  else
    ShowMessageFmt('Error %d', [Res]);
end;
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819422
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
// процедура в DLL
procedure GetStringFromDLL(Buffer: PAnsiChar; var dwSize: DWORD);
var
  OutStr: String;
begin
  OutStr := 'йцукен qwerty'; // как-то получили эту строку

  dwSize := Length(OutStr);

  if Buffer <> nil then
    Buffer := StrNew(PAnsiChar(OutStr));
end;



Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
// внешняя программа
procedure GetStringFromDLL(Buffer: PAnsiChar; var dwSize: DWORD);
...
procedure ReadString;
var
  MyStr: String;
  Size: DWORD;
  Buffer: PAnsiChar;
begin
  Size := 0;

  GetStringFromDLL(nil, Size);

  if Size > 0 then
  begin
    Buffer := GetMemory(Size);
    GetStringFromDLL(@Buffer, Size);
    MyStr := Buffer;
    FreeMemory(Buffer);

    ShowMessage(MyStr);
  end;
end;


Все равно не получаю то что надо...
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819424
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В моем примере заменить
_Vasilisk_
Код: pascal
1.
MyStr: String;

на
Код: pascal
1.
MyStr: WideString;
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819425
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,
Код: pascal
1.
2.
3.
4.
var
  MyStr: String;
   Buffer: PChar;
MyStr := Buffer;



и вы будете менять pchar, pansichar, widestring, string то ничего не получиться. подбором может только случайно получиться
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819427
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Ваш пример работает на ура.
Спасибо

Буду разбирать, чего я в этой технологии не понимаю.
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819440
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

А зачем в DLL длина буфера берется на 1 больше, если потом во внешней программе все равно идет уменьшение на эту же единицу?
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819444
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-TalkerА зачем в DLL длина буфера берется на 1 больше, если потом во внешней программе все равно идет уменьшение на эту же единицу?Мы передаем абстрактный PChar. Он заканчивается \0. Поэтому мы добавляем 1 в dll

Память мы выделяем функцией SetLength. В Делфи все строки заканчиваются \0, поэтому SetLength автоматически выделит память под этот \0. Отсюда -1
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819452
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

авторВ Делфи все строки заканчиваются \0
это где так?
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819454
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaonавторВ Делфи все строки заканчиваются \0это где так?Везде
Код: pascal
1.
2.
3.
4.
5.
6.
7.
Str: string;
begin
  Str := 'abc';
  ShowMessage(IntToStr(Ord(
    Str[Length(Str)] + 1
  )));
end;
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819456
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaon,

А как, по твоему, работает привидение к PChar?
...
Рейтинг: 0 / 0
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
    #39819476
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

авторА как, по твоему, работает привидение к PChar?
чудом, не иначе
включи range check, узнаешь много нового. никакого нуля сзади строки нет. ну и посмотри как приведение работает. подсказка: UStrToPWChar.
...
Рейтинг: 0 / 0
25 сообщений из 87, страница 1 из 4
Форумы / Delphi [игнор отключен] [закрыт для гостей] / DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]