Hint: C arrays are passed by reference

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Hint: C arrays are passed by reference

Сообщение Vadim » 02.04.2019 09:15:05

Есть модуль с заголовками функций к сишной библиотеке. Для примера, одна из функций выглядит так:
Код: Выделить всё
function VyrviGlaz(ar1: array of integer; count: integer): integer; cdecl;

Вопрос про передачу в неё "безразмерного" массива. Если он передаётся так, как приведено выше в примере кода, он передаётся по ссылке или по значению? Компилятор выдаёт предупреждение, как в заголовке. Только я не могу понять - это предупреждение, что массив надо передавать в функцию в виде адреса или компилятор всё-таки где-то там глубоко у себя внутри уже переделал параметр массива на ссылку?
Vadim
долгожитель
 
Сообщения: 3654
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Hint: C arrays are passed by reference

Сообщение wadman » 02.04.2019 10:36:04

Hint: C arrays are passed by reference
Any array passed to a C function is passed by a pointer (i.e. by reference).

То есть "где-то глубоко у себя внутри".
wadman
постоялец
 
Сообщения: 121
Зарегистрирован: 18.10.2016 15:54:28

Re: Hint: C arrays are passed by reference

Сообщение Vadim » 02.04.2019 11:38:41

wadman
И если я сделаю так:
Код: Выделить всё
function VyrviGlaz(@ar1: array of integer; count: integer): integer; cdecl;

Это уже будет совсем по сишному? Библиотечная функция меня поймёт?
Я проверить пока не могу, работа ишшо в полном разгаре... :-)
Vadim
долгожитель
 
Сообщения: 3654
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Hint: C arrays are passed by reference

Сообщение Снег Север » 02.04.2019 11:45:27

Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 1986
Зарегистрирован: 27.11.2007 16:14:47

Re: Hint: C arrays are passed by reference

Сообщение wadman » 02.04.2019 12:55:09

Vadim писал(а):Это уже будет совсем по сишному?

Оно уже по сишному, о чем компилятор просто предупреждает.
wadman
постоялец
 
Сообщения: 121
Зарегистрирован: 18.10.2016 15:54:28

Re: Hint: C arrays are passed by reference

Сообщение Дож » 02.04.2019 12:58:03

Код: Выделить всё
function VyrviGlaz(ar1: PInteger; count: integer): integer; cdecl;
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 795
Зарегистрирован: 12.10.2008 16:14:47

Re: Hint: C arrays are passed by reference

Сообщение Снег Север » 02.04.2019 13:50:38

На форуме по ссылке выше писали:
You cannot pass dynamic arrays to non-pascal dlls, because they are managed types and @a is not the same as @a[0,0].
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 1986
Зарегистрирован: 27.11.2007 16:14:47

Re: Hint: C arrays are passed by reference

Сообщение Дож » 02.04.2019 14:11:28

Снег Север, а тут и не динамические массивы, тут открытые массивы
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 795
Зарегистрирован: 12.10.2008 16:14:47

Re: Hint: C arrays are passed by reference

Сообщение daesher » 02.04.2019 15:45:39

А есть ли вообще смысл передавать открытые массивы без указания const? Технически это возможно (но не в cdecl), но крайне вредно ими забивать стек. Разве что число элементов будет совсем небольшим.
daesher
постоялец
 
Сообщения: 220
Зарегистрирован: 09.03.2010 22:17:14

Re: Hint: C arrays are passed by reference

Сообщение Vadim » 03.04.2019 19:52:51

В общем, для проверки всех высказанных тут идей была состряпана библиотечка с таким кодом:
Код: Выделить всё
#include <stdio.h>

void printarr(int *arr, int count)
{
  int i;
 
  for(i=0;i<count;i++)
  {
    printf("arr[%d] = %dn", i, arr[i]);
  }
}

Компиляция:
gcc -Wall -fPIC -c lib.c
gcc -shared -o libcore.so lib.o

И две тестовые программки:
Код: Выделить всё
{$mode objfpc}{$h+}
{Вариант №1.
В процедуру сишной библиотеки передаётся
указатель на первый элемент массива.}
program test1;

procedure printarr(arr: Pinteger; count: integer); cdecl; external 'libcore.so' name 'printarr';

Var
  a: array[0..5] of integer;
  i: integer;

Begin
  for i:=0 to 5 do
    a[i]:=i;
 
  i:=6;
  printarr(@a[0], i);

End.

Код: Выделить всё
{$mode objfpc}{$h+}
{Вариант №2.
В процедуру сишной библиотеки передаётся
сам массив.}
program test2;

procedure printarr(arr: array of integer; count: integer); cdecl; external 'libcore.so' name 'printarr';

Var
  a: array[0..5] of integer;
  i: integer;

Begin
  for i:=0 to 5 do
    a[i]:=i;
 
  i:=6;
  printarr(a, i);

End.

Обе программы выдают один и тот же результат. Так что оба варианта рабочие.

Снег Север. Вполне возможно, что во второй версии компилятора передача открытого массива в сишную процедуру не поддерживалось, а в третьей проблему исправили.

Добавлено спустя 4 минуты 32 секунды:
daesher писал(а):А есть ли вообще смысл передавать открытые массивы без указания const?

Риторический вопрос... :-D Я только делаю паскалевский заголовок для сишной библиотеки, а уж почему они там "const" не всунули - сии тайны мадридского двора мне неизвестны... ;-) От себя могу сказать, что без "const" подобные массивы в сишных библиотеках встречаются сплошь и рядом.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Vadim
долгожитель
 
Сообщения: 3654
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Hint: C arrays are passed by reference

Сообщение Снег Север » 03.04.2019 21:49:09

Vadim писал(а):Вполне возможно, что во второй версии компилятора передача открытого массива в сишную процедуру не поддерживалось, а в третьей проблему исправили.

Там речь шла про динамические массивы. У вас статический массив, который вы скармливаете процедуре, в виде ссылки или открытого массива. Т.е. вы доказали, что открытый массив в заголовке сишной процедуры - это ссылка. :D Что ж, примем к сведению.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 1986
Зарегистрирован: 27.11.2007 16:14:47

Re: Hint: C arrays are passed by reference

Сообщение Vadim » 04.04.2019 05:02:35

Снег Север
Динамический массив я тоже пробовал:
Код: Выделить всё
{$mode objfpc}{$h+}
{Вариант №2-1.
В процедуру сишной библиотеки передаётся
динамический массив.}
program test21;

procedure printarr(arr: array of integer; count: integer); cdecl; external 'libcore.so' name 'printarr';

Var
  a: array of integer;
  i: integer;

Begin
  SetLength(a, 6);
  for i:=0 to 5 do
    a[i]:=i;
 
  i:=6;
  printarr(a, i);

End.

но, сами понимаете, его в процедуру никак кроме открытого массива не передашь. Работает на ура... ;-)
Vadim
долгожитель
 
Сообщения: 3654
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Hint: C arrays are passed by reference

Сообщение Дож » 04.04.2019 05:14:20

его в процедуру никак кроме открытого массива не передашь

Код: Выделить всё
type
  TDynArr = array of Integer;

procedure PassedDynArr(A: TDynArr);
begin
  ...
end;
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 795
Зарегистрирован: 12.10.2008 16:14:47

Re: Hint: C arrays are passed by reference

Сообщение Vadim » 04.04.2019 08:57:24

Дож
Ну, это мы знаем. Примерно то же самое... :-)
Vadim
долгожитель
 
Сообщения: 3654
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Hint: C arrays are passed by reference

Сообщение Дож » 04.04.2019 15:35:49

Vadim, вы в предыдущем же сообщении написали, что динамический массив никак не передать в процедуру, -- но его можно передать, и я показал как. И нет: передать динамический массив не то же самое, что передать открытый массив.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 795
Зарегистрирован: 12.10.2008 16:14:47

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

Рейтинг@Mail.ru