Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / передача статического массива в функцию с сохранением ссылки на него как на динамический / 16 сообщений из 16, страница 1 из 1
27.06.2019, 11:55
    #39831042
Belotsky Serge
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Добрый день!

Нужно передать статический массив в функцию и сохранить ссылку на этот массив в динамическом массиве. Насколько корректен следующий код?:
Код: 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.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
type
 TRec = record
  A :integer;
  S :string;
 end;

 TDummyRec = record
  B :integer;
  DynRecs :array of TRec;
  constructor Init(AB :integer;  RecPtr :pointer);
  procedure Test;
 end;

 TMemoryStatDynRec = packed record
  RecsRefCnt :integer;
  RecsRefLen :integer;
  Recs :array[0..2]of TRec;
 end;

const
 MemoryStatDynRec :TMemoryStatDynRec = ( RecsRefCnt :1; RecsRefLen :3; Recs :((A:1; S:'1'), (A:2; S:'22'), (A:3; S:'333')));

{ TDymmyRec }

constructor TDummyRec.Init(AB :integer; RecPtr :pointer);
var
 i :integer;
begin
 B := AB;

 DynRecs := RecPtr;
end;

var
 DummyRec :TDummyRec;

procedure TForm1.FormCreate(Sender: TObject);
begin
 DummyRec.Init(5, @MemoryStatDynRec.Recs);
 DummyRec.Test;
end;

procedure TDummyRec.Test;
var
 i :integer;
 C :integer;
 SS :string;
begin
 for i := 0 to length(DynRecs)-1 do
  with DynRecs[i] do
   begin
    C := A;
    SS := S;
   end;
end;


...
Рейтинг: 0 / 0
27.06.2019, 14:52
    #39831185
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Belotsky SergeНасколько корректен следующий код?
Для 32-битного режима корректен.
...
Рейтинг: 0 / 0
27.06.2019, 14:59
    #39831193
black-manatee
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Если Вы используете код внутри цельного приложения, то не нужно передавать массив как ссылку. Используйте var.

Код: pascal
1.
procedure MyProc( var MyArray: TMyArray)



А если Вы собрались передавать ссылку куда нибудь вроде DLL, то нет, это не покатит.

Долго объяснять, но точно не покатит.

Итого, в любом случае, не надо так делать.
...
Рейтинг: 0 / 0
27.06.2019, 15:36
    #39831219
Belotsky Serge
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
black-manateeЕсли Вы используете код внутри цельного приложения, то не нужно передавать массив как ссылку. Используйте var.

Код: pascal
1.
procedure MyProc( var MyArray: TMyArray)



А если Вы собрались передавать ссылку куда нибудь вроде DLL, то нет, это не покатит.

Долго объяснять, но точно не покатит.

Итого, в любом случае, не надо так делать.

Пробовал я через var , компилятор не дает. Что-то вроде того, что я не могу dynamic array присвоить static array.
Можете привести полный пример на моем исходнике?

Мне не хочется дублировать статический массив в памяти из-за размера.

авторА если Вы собрались передавать ссылку куда нибудь вроде DLL, то нет, это не покатит.

Это почему? Pointer - он и в Африке. С учетом что и dll и приложение 32-х битные, а dll еще с дополнительном ограничением, должен быть скомпилирован в среде Delphi (чтобы не заморачиваться с некоторыми дельфовыми классами типа TList)
...
Рейтинг: 0 / 0
27.06.2019, 16:48
    #39831283
black-manatee
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Belotsky SergeПробовал я через var , компилятор не дает. Что-то вроде того, что я не могу dynamic array присвоить static array.
Можете привести полный пример на моем исходнике?

Мне не хочется дублировать статический массив в памяти из-за размера.

Да я слегонца тупанул. Не сразу понял что Вы хотите.
А вот нифига я не понял: зачем такие сложности ?
У Вас есть константа, ну и используйте ее в коде.
Зачем ее преобразовывать в динамический массив.
В Вашем случае:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
procedure TDummyRec.Test;
var
 i :integer;
 C :integer;
 SS :string;
begin
 for i := Low(MemoryStatDynRec.Recs) to High(MemoryStatDynRec.Recs) do
  with MemoryStatDynRec.Recs[i] do
   begin
    C := A;
    SS := S;
   end;
end;




Это почему? Pointer - он и в Африке. С учетом что и dll и приложение 32-х битные, а dll еще с дополнительном ограничением, должен быть скомпилирован в среде Delphi (чтобы не заморачиваться с некоторыми дельфовыми классами типа TList)
Pointer в Африке pointer. А структура на которую он указывает, в Африке может сильно отличаться от таковой в Европе.

К примеру Ваш TRec не объявлен как packed. Значит между поля структуры могут быть сдвинуты. string, который Вы передаете как одно из полей структуры, это по сути достаточно сложная структура, одно из полей которой ссылается на блок памяти, где значение строки определено. Но string в delphi, не может считаться dll безопасным. Структура описания строки может отличаться в зависимости от версии Delphi, настроек компиляции и т.д.

В общем массив структур, некоторые из полей которых - string нельзя передавать в dll по ссылке.
...
Рейтинг: 0 / 0
27.06.2019, 16:56
    #39831284
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Belotsky SergeС учетом что и dll и приложение 32-х битные,Так. Тут еще и dll нарисовались.

Озвучьте исходную задачу
...
Рейтинг: 0 / 0
27.06.2019, 17:25
    #39831303
Belotsky Serge
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
_Vasilisk_Belotsky SergeС учетом что и dll и приложение 32-х битные,Так. Тут еще и dll нарисовались.

Озвучьте исходную задачу

Я делаю что-то вроде Helper'а, чтобы проще было писать исходный код в самой dll.
Сам Helper описывается в главном коде и оформляется в виде record с функциями. Helper работает по данным из константного массива. Т.е. сначала 'инициализируется' Helper для заданного константного массива, затем вызываются методы Helper для выполнения определенных задач (формирования большого и сложного TList). Все это выполняется в коде dll и возвращается ссылка на этот TList (pointer). Константный массив - в виде *.inc включается каждый в свою dll. Модулей dll - несколько и каждый предназначен для загрузки из своего файла данных в этот самый унифицированный TList, который и возвращается в главную программу.

Дело в том, что все это работает. Но мне лень, для каждой новой dll городить похожий код, который хочется вынести куда-то в другое место.
Так понятнее? :)
...
Рейтинг: 0 / 0
27.06.2019, 17:42
    #39831310
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Belotsky SergeВсе это выполняется в коде dll и возвращается ссылка на этот TList (pointer).Привет мегаграблям!
Belotsky Serge
Код: pascal
1.
2.
3.
4.
 TRec = record
  A :integer;
  S :string;
 end;

строки тоже передаются в/из dll? Например, в составе TList?
Belotsky SergeНо мне лень, для каждой новой dll городить похожий код, который хочется вынести куда-то в другое место.Почему бы код код не вынести в отдельный Unit и в каждом проекте подключать этот юнит?
Belotsky SergeДело в том, что все это работает.Повезло. Или, наоборот, не повезло
...
Рейтинг: 0 / 0
28.06.2019, 07:21
    #39831446
black-manatee
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Тут понимаете какое дело. Взаимодействие dll и основного приложения таит в себе кучу опасностей. Даже если Вы все делаете канонично и стандартно.
string передавать в DLL нельзя.
Передавать строку как PChar можно, но на всякий случай нужно убедиться, что одна из dll не будет написана на старой версии PChar, где символы однобайтные.
integer передавать вроде как можно, но в одной системе это может быть 4 байта, а в другой 8.

Я для в рамках своей паранойи даже доходил до такого:

Код: pascal
1.
2.
3.
4.
5.
Type
  DWORD = CARDINAL;
...

if SizeOf(DWORD) <> 4 then raise Exception.Create('Ошибка 119. Сообщите разработчику...');



И поэтому, когда я увидел как лихо Вы передаете в DLL структуры со строками, у меня волосы дыбом встали.

Если не хотите длинными осенними вечерами трахаться с очень сложно вычисляемыми глюками, то постоянно думайте о возможных несоответствиях в типах.
Т.е. как в анекдоте: два презерватива, затем эпоксидка, затем скотч, и главное - никакого секса.
...
Рейтинг: 0 / 0
28.06.2019, 07:33
    #39831447
Belotsky Serge
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
_Vasilisk_Belotsky SergeВсе это выполняется в коде dll и возвращается ссылка на этот TList (pointer).Привет мегаграблям!
строки тоже передаются в/из dll? Например, в составе TList?
Belotsky SergeНо мне лень, для каждой новой dll городить похожий код, который хочется вынести куда-то в другое место.Почему бы код код не вынести в отдельный Unit и в каждом проекте подключать этот юнит?
Belotsky SergeДело в том, что все это работает.Повезло. Или, наоборот, не повезло

Нет, строки в TList для главного проекта не передаются, там все канонически. Строки содержатся только в константном массиве.

Пришел к выводу, что проще и надежнее оформить хелпер в виде отдельного модуля, который будет 'цеплять' каждая dll, которой это нужно. Ну а константный массив проще передавать по ссылке каждый раз в функцию хелпера (таких функций немного). Тут вы правы насчет отдельного юнита.
...
Рейтинг: 0 / 0
28.06.2019, 08:08
    #39831453
Belotsky Serge
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Belotsky SergeПришел к выводу, что проще и надежнее оформить хелпер в виде отдельного модуля, который будет 'цеплять' каждая dll, которой это нужно. Ну а константный массив проще передавать по ссылке каждый раз в функцию хелпера (таких функций немного). Тут вы правы насчет отдельного юнита.
PS: тут я ошибся, константный массив нельзя передать по ссылке :( Т.е. каждый раз будет "забиваться" стек функции значениями константного массива. Видимо придется использовать схему как в первом посте. Что же делать, кругом засада :( Модуль хелпера не может содержать константный массив. Но он ему нужен для работы.
...
Рейтинг: 0 / 0
28.06.2019, 10:21
    #39831491
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Belotsky Serge,

Нельзя присваивать динамические массивы как ДинамическийМассив := УказательНаСтатический, потому что динамический массив - это указатель на структуру (как и строки), а статический - просто область в памяти. Поэтому когда компилятор попытается что-то изменить в этом динамическом массиве - он будет писать в память где, по его мнению, находится служебная информация, а на самом деле - хрен знает что (другие переменные).
...
Рейтинг: 0 / 0
28.06.2019, 10:23
    #39831494
Василий 2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
black-manateeТут понимаете какое дело. Взаимодействие dll и основного приложения таит в себе кучу опасностей. Даже если Вы все делаете канонично и стандартно.
string передавать в DLL нельзя.
Передавать строку как PChar можно, но на всякий случай нужно убедиться, что одна из dll не будет написана на старой версии PChar, где символы однобайтные.
integer передавать вроде как можно, но в одной системе это может быть 4 байта, а в другой 8.

Я для в рамках своей паранойи даже доходил до такого:

Да вот это точно паранойя и эпоксидка с "никакого секса". Совместимость PChar достигается явным указанием PAnsi/WideChar, integer ни в какой системе не меняет размера, а тот тип, что меняет (Nativeint) по определению совпадает у либы и хост-приложения, т.к. разные разрядности система в принципе не даст подружить
...
Рейтинг: 0 / 0
28.06.2019, 12:10
    #39831571
black-manatee
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Василий 2Да вот это точно паранойя и эпоксидка с "никакого секса". Совместимость PChar достигается явным указанием PAnsi/WideChar
Именно это я собственно и имел ввиду вообще то, что PChar использовать не стоит

Василий 2integer ни в какой системе не меняет размера, а тот тип, что меняет (Nativeint) по определению совпадает у либы и хост-приложения, т.к. разные разрядности система в принципе не даст подружить
Да, Embarcadero оставила integer 4-х байтным. Видимо для совместимости. Да только это решение нифига не было очевидным. И есть ненулевая вероятность, что это изменится.
Кроме того, Вы можете к примеру в 32 битном приложении присваивать pointer-у integer, а потом перекомпилить под Win64. Очевидно у Вас будут проблемы.

Я к тому, что лучше потратить полчаса, чтобы подумать над потенциальной совместимостью типов для разных платформ, версий и т.д.
...
Рейтинг: 0 / 0
28.06.2019, 14:17
    #39831663
Василий 2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
black-manateeДа, Embarcadero оставила integer 4-х байтным. Видимо для совместимости. Да только это решение нифига не было очевидным. И есть ненулевая вероятность, что это изменится.
Кроме того, Вы можете к примеру в 32 битном приложении присваивать pointer-у integer, а потом перекомпилить под Win64. Очевидно у Вас будут проблемы.

Я к тому, что лучше потратить полчаса, чтобы подумать над потенциальной совместимостью типов для разных платформ, версий и т.д.
Мало что может быть менее очевидным, чем внезапно сделать integer платформозависимым. Для этих целей есть специально так названные Native типы (даже укуренные сишники и то по большей части соблюдают разумный порядок - size_t, INT_PTR и т.д.). Вот со string/PChar так поступили, и до сих пор такие вопросы всплывают.
...
Рейтинг: 0 / 0
28.06.2019, 14:47
    #39831681
black-manatee
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
передача статического массива в функцию с сохранением ссылки на него как на динамический
Василий 2Мало что может быть менее очевидным, чем внезапно сделать integer платформозависимым.
Изначально integer - это значение, целиком располагавшееся в регистре процессора.
В первых версиях turbo паскаля - integer был 16 битным.
В любом случае, если Вы учтете этот нюанс, хуже Вы точно не сделаете.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / передача статического массива в функцию с сохранением ссылки на него как на динамический / 16 сообщений из 16, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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