Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / DLL - Написать DLL, в ней функцию, которая возвращает массив записей. / 25 сообщений из 87, страница 1 из 4
20.05.2019, 16:55
    #39815407
SQL-Talker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
Возникла необходимость на 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
20.05.2019, 17:00
    #39815410
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
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
20.05.2019, 17:34
    #39815431
ёёёёё
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
SQL-Talker,

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

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

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

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

С масивом всё просто, смотри похожие функции в WinAPI, там везде функция имеет два логичесикх варианта вызова: определение необходимого размера и собственно сама работа. Т.е. необходимую память выделяет вызывающая сторона.
...
Рейтинг: 0 / 0
28.05.2019, 15:07
    #39819368
SQL-Talker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
Пытаюсь вернуть строку из 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
28.05.2019, 15:36
    #39819394
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
SQL-Talker,
зачем
Код: pascal
1.
GetMemory(Size * 2);


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

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

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

одно и тоже?
...
Рейтинг: 0 / 0
28.05.2019, 16:31
    #39819421
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
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
28.05.2019, 16:32
    #39819422
SQL-Talker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
Код: 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
28.05.2019, 16:36
    #39819424
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
В моем примере заменить
_Vasilisk_
Код: pascal
1.
MyStr: String;

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



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

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

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

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

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

авторВ Делфи все строки заканчиваются \0
это где так?
...
Рейтинг: 0 / 0
28.05.2019, 17:56
    #39819454
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
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
28.05.2019, 17:57
    #39819456
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DLL - Написать DLL, в ней функцию, которая возвращает массив записей.
makhaon,

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

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


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