Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Ада и другие языки _ Заголовки Windows, Ada

Автор: TarasBer 8.02.2011 20:28

Я поставил пакет win32ada, он создал папку include\win32ada
Если написать первой строкой test.gpr with "win32ada", то среда ругается при открытии пакета:

[2011-02-08 16:25:57] C:\Program Files\ADA\projects\TEST\test.gpr:1:06: unknown project file: "win32ada"
[2011-02-08 16:25:57] Error while loading project 'C:\Program Files\ADA\projects\TEST\test.gpr'. Loading the default project.

Ну я это убрал.
Добавил в test.gpr строчку

for Source_Dirs use ("..\..\include\win32ada\**");

Пишу в test.adb with win32.winuser (вроде все основные функции, типа окно нарисовать итд, там).
Компилирую.

gnatlink "C:\Program Files\ADA\projects\TEST\test.ali" -shared-libgcc -g -g -fprofile-generate -o "C:\Program Files\ADA\projects\TEST\test.exe"
c:/program files/ada/bin/../libexec/gcc/i686-pc-mingw32/4.3.6/ld.exe: cannot find -lwin32ada
collect2: ld returned 1 exit status
gnatlink: error when calling C:\Program Files\ADA\bin\gcc.exe
gnatmake: *** link failed.

[2011-02-08 16:28:19] process exited with status 4 (elapsed time: 06.26s)

Что делать?

Автор: volvo 8.02.2011 21:07

Цитата
вроде все основные функции, типа окно нарисовать итд, там
Вот на это я бы вообще не закладывался, некоторые вещи будут не там, где ты ожидаешь.

А по проводу ошибки линкера - в проектах, использующих WinAPI - вот здесь есть пример минимального Win32-приложения: http://users.ncrvnet.nl/gmvdijk/w32first.zip , скачай его, и вот с таким GPR-файлом у меня только что откомпилировалось и заработало:
with "win32ada";

project Test is

for Source_Dirs use (".");
for Main use ("first.adb");

package Builder is
for Default_Switches ("ada") use ("-O2");
end Builder;

package Compiler is
for Default_Switches ("ada") use ("-O3");
end Compiler;

package Linker is
for Default_Switches ("ada") use ("-s");
end Linker;

end Test;

Очень странно, что тебе приходится прописывать пути вручную. Дело в том, что в папке \GNAT\версия\lib\gnat после установки Win32Ada должен появиться файл win32ada.gpr, имеющий следующее содержимое:
project Win32Ada is

for Languages use ("ada");

for Source_Dirs use ("../../include/win32ada");

for Library_Dir use "../../lib/win32ada";
for Library_Name use "win32ada";
for Externally_Built use "true";

end Win32Ada;

, вот строка with в твоем "test.gpr" подключает этот файл, и не надо вручную прописывать пути. У тебя что, нет этого файла? Каждый пакет, который ты устанавливаешь, должен создавать такой GPR, в котором содержатся "свои" настройки, чтоб пакет использовать - достаточно подключить его через With в своем проекте...

Автор: TarasBer 8.02.2011 21:17

> У тебя что, нет этого файла?

Файл есть.
Если написать
with "..\..\lib\gnat\win32ada.gpr";
то при открытии выдаётся простыня ошибок на много страниц.

Но файл типа обнаружен, наверное.

А на просто with "win32ada"; он просто говорит, что не может найти.
В среде галочек и папок никаких выставить не надо?

Автор: volvo 8.02.2011 21:33

Попробуй создать новый проект, и когда он будет создан - правой кнопкой мыши щелкнуть на корневом узле в Project View (название твоего проекта), и в меню выбрать Project -> Dependencies. Откроется окошко, в котором никаких зависимостей не будет (ну, понятно, проект-то новый). Жмешь кнопку "Add from known projects". Если в появившемся списке известных проектов тоже нет Win32Ada - значит, установка не завершилась корректно, где-то что-то недопрописано в настройках. Если есть - просто отмечай его галочкой и IDE сделает все остальное сама...

Автор: TarasBer 8.02.2011 21:51

> Если в появившемся списке известных проектов тоже нет Win32Ada - значит, установка не завершилась корректно, где-то что-то недопрописано в настройках.

А там нету.
Странно, вроде винада запустилась, что-то в консольном окне с процентами долго показывала...

Автор: TarasBer 10.02.2011 18:29

Снес ГНАТ, переставил всё.
Если прямо из среды дописать with "win32ada", то пересобирается нормально, но потом при открытии опять ругается. Да, в том списке зависимостей опять пусто.

Автор: volvo 10.02.2011 19:31

Хм... Как вариант попробуй в зависимостях добавить через "Add from file" (у тебя ж Win32Ada.gpr есть, ты говоришь) вот этот самый файл: GNAT\2010\lib\gnat\win32ada.gpr ... И сразу после того, как это сделал (и прогрессбар исчез) - жми Project -> Save All... Только что попробовал - тоже отработало. А потом попробуй закрыть среду, и посмотреть что записано в первой строке твоего GPR-файла.

И, если опять будет ругаться при переоткрытии проекта - сделай скриншот, чтоб было видно полный текст ошибки, и содержимое Project View...

Автор: TarasBer 10.02.2011 20:02

> А потом попробуй закрыть среду, и посмотреть что записано в первой строке твоего GPR-файла.

with "..\..\lib\gnat\win32ada.gpr";

> И, если опять будет ругаться при переоткрытии проекта

Не, теперь нормально открылось.
Всё, наконец-то я могу перейти к окнам.

> - сделай скриншот

Если бы я в прошлый раз, когда добавил полный путь к файлу, сделал снимок экрана, то на нём бы самой интересной деталью был выродившийся ползунок в списке ошибок (там строчек за 1000 было).

Автор: TarasBer 11.02.2011 17:02

> А по проводу ошибки линкера - в проектах, использующих WinAPI - вот здесь есть пример минимального Win32-приложения: http://users.ncrvnet.nl/gmvdijk/w32first.zip , скачай его, и вот с таким GPR-файлом у меня только что откомпилировалось и заработало:

У меня не компилируется (ругается на слово "or").


Эскизы прикрепленных изображений
Прикрепленное изображение

Автор: volvo 11.02.2011 18:13

Странно. Значит, я не оттуда брал тот тестовый пример, которым пользовался (скачан он был давно). Или компилировал другой файл...

В любом случае - ничего страшного. Строкой ниже указано, что делать. Смотришь, с каким типом у компилятора вышла заминка (в данном случае это Interfaces.C.unsigned), и добавляешь либо локально в этой функции, либо глобально для всего пакета, если подобная ошибка встречается несколько раз

use type Interfaces.C.unsigned;

То же самое касается и 83 строки, там придется добавить use type Interfaces.C.unsigned_long

Хинт: чтобы не подключать пакет Interfaces.C, можно заменить тип из Interfaces.C соответствующим типом из Win32. Например, Interfaces.C.unsigned = Win32.UINT, а Interfaces.C.unsigned_long = Win32.DWORD

Автор: TarasBer 14.02.2011 15:22

Программу я скомпилировал.
Но окно белое.
Новый вопрос: что надо написать, чтобы скомпилировалось
Wnd_Class.hbrBackground := Win32.WinUser.Color_BtnFace + 1;
?

Автор: volvo 14.02.2011 17:05

   function To_HBRUSH is new Ada.Unchecked_Conversion
(Integer, Win32.Windef.HBRUSH);

-- ...
Wnd_Class.hbrBackground := To_HBRUSH (Win32.WinUser.Color_BtnFace + 1);

Автор: TarasBer 21.02.2011 16:25

Вопрос: в каком модуле описаны константы wmsz_TopLeft итд?
Я ещё много вопросов буду задавать вида "в каком модуле описано что-то там". Вообще взаимодействие с виндой сделано очень неудобно, на каждый чих свой тип, всех их надо приводить, а то и конвертировать, на каждый чих компилятора долго подбирать какой тип в какой надо преобразовать, чтобы это скомпилировалось, кошмар.
Да ещё и куча функций, требующих параметр по ссылке, а давать ссылку на локальную переменную нельзя, приходится портить код и заводить глобальные переменные для того, чтобы применить их в локальной процедуре и передать ссылку на них, либо заводить указатель и выделять память при входе в процедуру, короче, одни костыли кругом. И это всё из-за того, что нет out -параметров для функций, почему их раньше не ввели?

Автор: TarasBer 21.02.2011 17:11

WM_SIZING тоже куда дели?

Автор: volvo 21.02.2011 17:12

Цитата
в каком модуле описаны константы wmsz_TopLeft итд?
Не описаны они вообще. Кому надо - тот открывает http://msdn.microsoft.com/en-us/library/ms632647%28v=vs.85%29.aspx, смотрит там на значения констант, и пишет себе в пакет:

WMSZ_TOPLEFT : constant := 4;
WMSZ_TOPRIGHT : constant := 5;
-- и так далее ...


Цитата
Вообще взаимодействие с виндой сделано очень неудобно, на каждый чих свой тип, всех их надо приводить, а то и конвертировать
Взаимодействие сделано в стиле языка. То, что в WinAPI куча дублирующих друг друга типов - это только проблемы WinAPI. Ада не может позволить программисту взять тип Integer, и использовать его как HBRUSH. Потому, что это сегодня они совпадают по размеру. А завтра (с выходом новой версии Windows или нового сервис-пака) могут и перестать совпадать. Именно поэтому, кстати, в свое время перестали работать многие программы при переходе Win16 -> Win32. А пользовались бы правильными типами (а не уверенностью в том, что размер одного будет вечно совпадать с размером другого) - работало бы до сих пор, достаточно было бы просто перекомпилировать код.

Цитата
на каждый чих компилятора долго подбирать какой тип в какой надо преобразовать, чтобы это скомпилировалось, кошмар.
Ничего не надо подбирать. Достаточно посмотреть на тип переменной-приемника, и привести тип переменной-источника (или выражения) к нему.

Цитата
Да ещё и куча функций, требующих параметр по ссылке, а давать ссылку на локальную переменную нельзя, приходится портить код и заводить глобальные переменные для того, чтобы применить их в локальной процедуре и передать ссылку на них, либо заводить указатель и выделять память при входе в процедуру, короче, одни костыли кругом.
Пример костылей можно посмотреть? Что-то я особых костылей, связанных с необходимостью передать по ссылке второй параметр BeginPaint, не вижу:

   function Window_Proc (hwnd    : Win32.Windef.HWND;
message : Win32.UINT;
wParam : Win32.WPARAM;
lParam : Win32.LPARAM) return Win32.LRESULT is

use Interfaces.C;
-- ...
My_DC : Win32.Windef.HDC;
bResult : Win32.BOOL;
Paint_Record : aliased Win32.Winuser.PAINTSTRUCT;

begin

case message is

-- ...

when Win32.Winuser.WM_PAINT =>
My_DC := Win32.Winuser.BeginPaint (hwnd, Paint_Record'Access);

-- ... Рисуем на My_DC ...

bResult := Win32.Winuser.EndPaint (hwnd, Paint_Record'Access);

when others => return
Win32.Winuser.DefWindowProc (hwnd, message, wParam, lParam);

end case;
return 0;

end Window_Proc;
(пример из совершенно рабочей программы, валялся у меня на флешке). Что я не так делаю?

Автор: TarasBer 21.02.2011 17:24

> Не описаны они вообще. Кому надо - тот открывает MSDN -> WM_SIZING Message, смотрит там на значения констант, и пишет себе в пакет:

Ну сегодня константы описаны так, а в другой системе иначе. И перекомпилированная программа неверно работает. Ну в МСДН-то посмотреть я догадался, но как-то это неправильно, по-моему.

> То, что в WinAPI куча дублирующих друг друга типов - это только проблемы WinAPI.

Ну при переводе заголовков-то можно было все нужные типы к одному свести?

> Пример костылей можно посмотреть?

Например, в том примере:

msg : Win32.Winuser.LPMSG := new Win32.Winuser.MSG;
Result := TranslateMessage(ac_Msg_T(msg));

А потому, что если просто написать

message: aliased Msg; // локально
Result := TranslateMessage(message'access);

то компилятор выдаёт "non-local pointer cannot point to local object".

Автор: volvo 21.02.2011 17:45

А просто ради интереса проверь, вот такое будет компилироваться (и работать, разумеется, понятно что просто компиляция никому на фиг не сдалась) :

      Message: aliased Msg; -- локально
Message_Ptr: Win32.Winuser.ac_MSG_t := Message'Unchecked_Access;

Result := win32.Winuser.TranslateMessage(Win32.WinUser.ac_Msg_t(Message_Ptr));

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

Автор: TarasBer 21.02.2011 18:48

Unchecked_Access скомпилировался и заработал, спасибо (я сразу передавал в процедуру Message'Unchecked_Access, без промежуточной переменной Message_Ptr).

Автор: TarasBer 25.02.2011 17:49

Я таки не понял, что происходит с исключениями внутри оконной функции?
Я зашил содержимое главного оконного цикла (while getmessage(...)) в блок begin-except-end, а в оконной функции на нажатие ЛКМ сделал деление на ноль. При нажатии ЛКМ прога вылетела.

Автор: volvo 25.02.2011 20:44

Хм. Извини, а с каких пор исключение может покидать пределы оконных функций и Callback-ов? Этого никогда нельзя было делать, насколько я помню. То, что где-то это работало - не повод думать, что оно должно было там работать.

Исключение должно быть обработано до выхода из оконной функции, и не должно передаваться дальше. Иначе система возьмет на себя его обработку. К чему это приводит - ты уже видел...

Автор: Гость 25.02.2011 21:11

> Хм. Извини, а с каких пор исключение может покидать пределы оконных функций и Callback-ов?

Впервые слышу про такое.
В Д7 это работало, да.
А с чего это не должно работать?

> Иначе система возьмет на себя его обработку.

Система разве не передаёт его выше (то есть в мой обработчик в итоге)?

Автор: volvo 25.02.2011 22:41

Цитата
А с чего это не должно работать?
http://www.rsdn.ru/forum/cpp.applied/3080973.flat.aspx и не должно.

Если в Дельфи исключения реализованы поверх SEH (а никакой причины не сделать этого я не вижу, система строго завязана под одну ОС, чего б не использовать везде только структурные исключения, если других-то и не может быть?), то все будет работать, разумеется... С другими языками - особенно с теми, которые работают не только на одной-единственной ОСи будет проблема. Естественно, что Ada exceptions не имеют к SEH никакого отношения, поэтому облом с ловлей исключений, выброшенных в CallBack-е.

Автор: volvo 26.02.2011 0:43

Значит, смотри. Пользуемся возможностями Ады:

Пакет Err

with Ada.Exceptions; use Ada.Exceptions;
with Ada.Task_Termination; use Ada.Task_Termination;
with Ada.Task_Identification; use Ada.Task_Identification;

package Err is

protected End_Of is
procedure World(C : Cause_Of_Termination;
T : Task_ID; X : Exception_Occurrence);
end End_Of;

end Err;

+
with Ada.Exceptions;
with Ada.Text_IO;

package body Err is

protected body End_Of is
procedure World(C : Cause_Of_Termination;
T : Task_ID; X : Exception_Occurrence) is
My_File : ada.Text_IO.File_Type;
begin
case C is
when Normal => null;
when Abnormal =>
Ada.Text_IO.Put_Line ("Abnormal termination of Task" & Image(T));
when Unhandled_Exception =>
Ada.Text_IO.Create(My_File, Ada.Text_IO.Out_File, "My.txt");
Ada.Text_IO.Put_Line (My_File, "Unhandled exception in Task : " & Image(T));
Ada.Text_IO.Put_Line (My_File, Exception_Information(X));
Ada.Text_IO.Put_Line (My_File, "End logging");
Ada.Text_IO.Close (My_File);
end case;

end World;
end End_Of;

end Err;

(Исправил на вывод в файл, иначе могут быть проблемы с запуском вне среды)... Что это дает?

Подключаешь этот пакет, и в самом начале основной процедуры:

with Err; use Err;
with Ada.Task_Termination;

procedure Main is
-- ...
begin
Ada.Task_Termination.Set_Dependents_Fallback_Handler(End_Of.World'Access);
-- ...
Вот сейчас специально нашел машину с Windows XP, запустил там программу, которая из WndProc бросает исключение (то самое деление на 0). Вот чего показывает:
N:\Just_Test\debug\main
Unhandled exception in Task : main_task_003E4008
Exception name: CONSTRAINT_ERROR
Message: wndproc.adb:59 divide by zero
Call stack traceback locations:
0x401e99 0x401f08 0x7e418732 0x7e418814 0x7e4189cb
0x7e4196c5 0x401e1d 0x4017a6 0x401235 0x4012a6 0x7c817075

End logging

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

P.S. В случае Ады проблем еще, похоже, добавляет GCC. Погугли на тему +"windows callback" +exceptions, и на тему dwarf2 vs sjlj exceptions

Автор: TarasBer 5.03.2011 16:02

В общем я тут сделал первую оконную программу на Аде.

Прикрепленный файл  wintest.rar ( 24.2 килобайт ) Кол-во скачиваний: 343


Ну и куча вопросов накопилась.

1. Зачем помимо INT ввели тип LONG, который от -2**31 до 2**31-1? В чём прикол?

2. У меня, например, есть функция. Принимает массив, который может быть ооочень длинным. Массив может быть передан в функцию либо сразу, как переменная, либо как результат вычисления выражения, либо как агрегат, то есть нужен именно in-параметр. Внутри функции над массивом производятся какие-то операции. Над самим параметром операции запрещены, поэтому первой строчкой функции стоит копирование
copy_a: arr := a;
Понятно, что если массив передаётся из переменной, то тут явно происходит то, что в Паскале делалось неявно. Но если массив передаётся как результат вычислений, то он изначально сидит на стеке, и если внутри функции все операции делаются с copy_a (а изначальное a даже не упоминается), то делать копирование из стека в стек просто бессмысленно. Умеет ли компилятор убирать копирование в таких случаях?

3. Агрегат при передаче в функцию не работает, если внутри только 1 параметр. f((a)) - это вызов функции от числа (a) или от массива (a)? Вот компилятор и запрещает так передавать 1-элементные массивы.
Но если у разработчиков языка явно была клавиатура только с одним типом скобочек, то сейчас у всех есть [ и ], которые можно разрешить применять для агрегатов. f(a) - передача числа, f([a]) - передача 1-элементного массива, f((a)) - неопределённость, запретить, не нужна.

4. Подобно очень опасной описке в С между == и =, в Аде есть очень опасная возмжность написать and вместо and then, "благодаря" которой будет выполняться то, что выполняться не должно. Это серьёзный изъян языка. Зачем для операции, которая нафиг не нужна в большей части случаев (вычисление выражения по полной схеме), оставили привычную запись, а для реально нужной операции сделали непривычную и длиную запись? Почему бы не оставили and и or для неполного вычисления, а для полного сделали бы, например, and necessarily и or necessarily?

5. Тот код из архива занимает 100 кб, но компилируется в мегабайт. В этом мегабайте последние 2/3 - это чистый текст. Как его скомпилировать в более приемлемый размер?

Автор: volvo 5.03.2011 20:13

Цитата
1. Зачем помимо INT ввели тип LONG, который от -2**31 до 2**31-1? В чём прикол?
Ввели все типы, которые описаны в "Interfaces.C".

С типом Long_Integer вообще отдельная история, на разных системах у него может быть разная разрядность, поэтому он стоит особняком. Видимо, поэтому его и в Win32Ada добавили особняком. Опять же, грядет переход на 64-бита, кто знает, что там с long-ом будет...

Цитата
Умеет ли компилятор убирать копирование в таких случаях?
По крайней мере, должен уметь. Если не умеет - надо сообщать об этом, как о баге.

Цитата
Агрегат при передаче в функцию не работает, если внутри только 1 параметр
Угу. Давай договоримся, что если кто-то не умеет передавать одно значение через агрегат - это ни разу не проблема языка:
type T is array (Positive range <>) of integer;
procedure Foo (arr : T) is
begin
for i in arr'Range loop
Ada.Text_IO.Put_Line (Integer'Image (arr (i)));
end loop;
end Foo;

-- ...
Foo (arr => (1 => 1)); -- Что-то не так?


Лишние скобки не нужны, не надо язык превращать в Perl...

Цитата
Зачем для операции, которая нафиг не нужна в большей части случаев (вычисление выражения по полной схеме), оставили привычную запись, а для реально нужной операции сделали непривычную и длиную запись?
С точки зрения англоязычного программиста как раз запись
if A > 0 and then Arr (A) = Value then
является более наглядной. "Выполнять второе действие только тогда, когда первое выполнилось". Аналогично и с or else. А то, что другой язык программирования приучил программиста писать and везде - это опять же не проблемы Ады.

Цитата
Тот код из архива занимает 100 кб, но компилируется в мегабайт. В этом мегабайте последние 2/3 - это чистый текст. Как его скомпилировать в более приемлемый размер?
Это я чуть позже гляну...

Автор: TarasBer 5.03.2011 20:26

> С точки зрения англоязычного программиста как раз запись
if A > 0 and then Arr (A) = Value then
является более наглядной. "Выполнять второе действие только тогда, когда первое выполнилось". Аналогично и с or else.

А запись if (f(A) > 0) and necessarily (g(A) > 0) тоже тогда наглядна - вычислять второе условие обязательно.

> А то, что другой язык программирования приучил программиста писать and везде - это опять же не проблемы Ады.

Опасность в том, что можно случайно забыть одно слово и получить некорректный код (полный аналог "случайно забыть один символ и..."). Да, в варианте с necessarily тоже опасность есть, что забудешь слово, и что-то не будет выполняться, но проявляться она будет намного реже, поскольку схема полного вычисления выражения нужна крайне редко (мне вообще никогда не пригождалась). Логично же для более частого случая применять более короткую запись, чтобы случайно не написать экзотический вариант.

Автор: volvo 5.03.2011 22:07

Цитата
Как его скомпилировать в более приемлемый размер?
При линковке добавил -s:

gnatlink F:\Programs\Ada\wintest\wintest\opt\wintest.ali -shared-libgcc -g -fprofile-generate -s
-LD:\GNAT\2009\lib\win32ada\ -lwin32ada -o F:\Programs\Ada\wintest\wintest\opt\wintest.exe

, от размера осталась едва ли треть (275К). Из IDE это делается Switches -> Ada Linker -> (включить) Strip symbols в свойствах проекта.

Кстати, откомпилировал твой проект со всеми Warning-ами (в свойствах - кнопка Warnings, и щелкнуть на Activate every optional warning) - у меня от оранжевого аж в глазах зарябило. Там и предупреждения о лишних with/use, и о том, что типы не надо подключать, они уже подключены и ты делаешь двойную работу, и то, что неизменно в ходе процедуры/функции и можно его описать как constant... Боюсь даже включать Style Check...

Автор: -TarasBer- 5.03.2011 22:26

> Кстати, откомпилировал твой проект со всеми Warning-ами

Так там по умолчанию не все включены?

> (в свойствах - кнопка Warnings, и щелкнуть на Activate every optional warning)

Блин, точно, есть такое подменю в том подменю.

> Там и предупреждения о лишних with/use, и о том, что типы не надо подключать, они уже подключены и ты делаешь двойную работу, и то, что неизменно в ходе процедуры/функции и можно его описать как constant...

Ну это да, надо исправить.

> , от размера осталась едва ли треть (275К).

Всё равно много.

Автор: volvo 5.03.2011 23:21

Посмотрю, что можно еще сделать...

Автор: TarasBer 9.03.2011 14:02

В общем, включил я ВСЕ предупреждения.
И выключил.

"Внимание: к формальному параметру нет обращения".
То есть он какбэ предлагает мне убрать параметр из заголовка функции.
Куда я его уберу, это функция для подстановки в качестве параметра функционального типа.

"Осторожно, к переменной после присваивания нет обращений".
А шо робыть, если эта функция зачем-то возвращает не нужное мне значение, которое надо непременно куда-то записать.

Всё-таки, какие предупреждения надо поставить, а какие не надо?

Ещё вопрос: в модуле Parser.ads как функцию Val_Number (ну которая используется в Do_Function и Do_Func_List) перенести в параметры шаблона? А то она принимает Key_Arr, а он задан как тип, производный от того, что идёт в параметрах шаблона, то есть описать его до функции Val_Number нельзя.

Автор: volvo 9.03.2011 18:09

Цитата
То есть он какбэ предлагает мне убрать параметр из заголовка функции.
Нет, он предлагает тебе либо убрать параметр из заголовка, либо отключить выдачу предупреждения:

   pragma Warnings (Off, "formal parameter ""lParam"" is not referenced");
pragma Warnings (Off, "formal parameter ""wParam"" is not referenced");
procedure Block( hWnd : in out Win32.Windef.HWND;
Msg : in out Win32.UINT;
wParam : in out Win32.WPARAM;
lParam : in out Win32.LPARAM;
Result : out Win32.LRESULT;
Continue : out boolean) is
pragma Warnings (On, "formal parameter ""lParam"" is not referenced");
pragma Warnings (On, "formal parameter ""wParam"" is not referenced");
begin
Result := 0;
Continue := False;
end;


Цитата
"Осторожно, к переменной после присваивания нет обращений".
А шо робыть, если эта функция зачем-то возвращает не нужное мне значение, которое надо непременно куда-то записать.
А вот тут есть 2 пути. Либо предупредить компилятор, что это особенность библиотеки (работа с функциями, которые все-таки должны вернуть результат) и на результат не надо обращать внимания, либо работать с определенными вещами не как с функциями, а как с процедурами.

По варианту №1: ты в файле wintestmain.adb внутри функции Graph используешь API-шную функцию SetPixel, из-за чего тебе нужна "лишняя" переменная С типа COLORREF, так? Можно сделать вот так:

   function Graph(Func: Parsed_Function) return boolean is

procedure SetPixelProc
(hDC : Win32.Windef.HDC;
X : Win32.INT;
Y : Win32.INT;
crColor: Win32.Windef.COLORREF);
pragma Import (StdCall, SetPixelProc, "SetPixel");

-- ... Дальше всё как было, но вместо обращения к функции SetPixel
-- будет обращение к процедуре SetPixelProc - переменная С уже не нужна.


По варианту №2:
   function Graph(Func: Parsed_Function) return boolean is

c : COLORREF; Unreferenced ©; -- Компилятор тут же перестанет паниковать


Цитата
Всё-таки, какие предупреждения надо поставить, а какие не надо?
Все-таки, я бы оставил все...

Чуть позже закончу перевод очередных обзоров с AdaCore, один из них касается именно работы с предупреждениями, ссылку запощу сюда.

Цитата
А то она принимает Key_Arr, а он задан как тип, производный от того, что идёт в параметрах шаблона
Проблема не в этом. Проблема - в том, что тебе для того, чтобы получить тип Key_Arr, надо инстанцировать другой шаблонный модуль. Это невозможно сделать при описании параметров настройки.

Автор: TarasBer 9.03.2011 18:41

> Нет, он предлагает тебе либо убрать параметр из заголовка, либо отключить выдачу предупреждения:
> ...
> c : COLORREF; Unreferenced ©;

Ладно, понял.

Ещё такой момент: если включить галочки в Validiting Checking Mode, то программа падает при запуске на строчке

NAN: constant f80 := Get_NAN;

Но мне действительно нужна такая константа, чтобы показать, что в этой точке график рисовать не надо.

Дальше, проверка стиля.
Ругается на то, что я выравниваю двоеточия табами.

Как надо? Пробелы мне не нравятся.

"слишком длинная линия"
Это он про комментарий из 70 русских букв, который он посчитал за 140.

"тело подпрограммы не имеет предварительного описания"
Чисто внутренняя подпрограмма же, зачем мне её описывать

"надо написать and then вместо просто and"
За это спасибо.
Трудно нигде не ошибиться в этом.

Ещё несколько предупреждений внутри стандартного (не моего) пакета. Что делать?

"неявное разыменование"
В смысле?

Автор: volvo 9.03.2011 20:11

Цитата
Ещё такой момент: если включить галочки в Validiting Checking Mode, то программа падает при запуске на строчке
NAN: constant f80 := Get_NAN;
Угу. Значит, включай все, кроме "Floating Point Values" (эта галка добавляет ключ gnatVf, при наличии которого любое действие с вещественными числами проверяется на валидность, а NaN - это невалидный результат операции)

Цитата
Дальше, проверка стиля.
Ругается на то, что я выравниваю двоеточия табами.
Как надо? Пробелы мне не нравятся.
Табами оно тем более не разрешит (если включено "No horizontal tabs"). Мы выравниваем пробелами. Все остальное не проходит проверку.

Цитата
"слишком длинная линия"
Это он про комментарий из 70 русских букв, который он посчитал за 140.
Разбей на 2 строки, по 35 символов.

Цитата
Чисто внутренняя подпрограмма же, зачем мне её описывать
Потому что положено. Причем в алфавитном порядке. Если ты не сделаешь этого - это сделает сам компилятор, но Style Checker об этом ничего знать не хочет, он тебя предупреждает, что прототип подпрограмма не описан.

Цитата
Ещё несколько предупреждений внутри стандартного (не моего) пакета. Что делать?
Либо исправить и пересобрать стандартные пакеты, либо не обращать внимания.

Цитата
"неявное разыменование"
В смысле?
В смысле,
Form.ID := To_HMENU(integer(LastID));

это неправильная запись. Правильно (и это сделает сам компилятор) - вот так:
Form.all.ID := To_HMENU(integer(LastID));

Но все шишки падают опять же на программиста.

Автор: TarasBer 10.03.2011 16:48

> Проблема не в этом. Проблема - в том, что тебе для того, чтобы получить тип Key_Arr, надо инстанцировать другой шаблонный модуль. Это невозможно сделать при описании параметров настройки.

А как выкручиваться-то?

Ещё компилятор выдаёт предупреждение, если Initialize-Finalize-Adjust находятся в private -части ads файла.
Что определение этой процедуры перекрывает определение на линии, где я объявил тип.

Автор: volvo 10.03.2011 22:19

Цитата
А как выкручиваться-то?
Ты ж выкрутился. Зачем тебе выносить эту функцию в параметры шаблона, расскажи? Как ты ее описывать собрался? Вот просто пример приведи, неважно, пускай некомпилируемый, как ты хочешь чтоб это работало...

Цитата
Ещё компилятор выдаёт предупреждение, если Initialize-Finalize-Adjust находятся в private -части ads файла. Что определение этой процедуры перекрывает определение на линии, где я объявил тип.
Насколько я помню, так себя ведет только GNAT, по этому поводу даже есть открытый баг в бегтрекере. Aonix ObjectAda не вякает по этому поводу. Тут есть 2 замечания: во-первых, если ты создаешь новый тип, первый в иерархии (то есть, наследуешься от Ada.Finalization.Controlled, а не от его потомка), то всегда добавляй перед прототипом описатель overriding. Во-первых, это поможет поймать опечатки, по-вторых, ты ясно указываешь компилятору, что тебе не надо перегружать функции, а надо именно заменить. http://vlady.uzelok.net/smf/index.php?topic=495.msg2630;topicseen#msg2630

Во-вторых, чего не указываешь, что type Parsed_Function is tagged private; ? Он же теговый, поскольку наследуется от Controlled, который сам по себе теговый. Не, я понимаю, что компилятор сам это добавит (как и virtual в С++, если ты забыл случайно описать функцию как виртуальную в наследнике, когда у предка эта функция уже была виртуальна), но все-таки лучше делать это программисту, с первого взгляда должно быть видно, что за тип, в твоем случае этого не видно.

А вообще эта проблема (предупреждения при описании этих трех процедур в приватной части) растет вот отсюда: если у тебя есть нетэговый тип, то может быть вот такая заморочка (пример приводил Adam Beneschan)

package Pack2 is
type T2 is new Pack1.T; -- для типа описана операция/процедура Op
-- Естественно, T2 наследует Op

private
overriding procedure Op (X : T2);
end Pack2;
Теперь в зависимости от того, где будет вызываться T2.Op (в смысле, видима ли там приватная часть модуля Pack2 или нет) под P2.Op может подразумеваться разная функциональность. Где-то унаследованная от T1.Op, где-то - переопределенная.

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

Автор: TarasBer 11.03.2011 14:30

> Ты ж выкрутился.

Круто, теперь у моего разборщика выражений есть новый функционал: я могу в один и тот же разборщик подсовывать разные функции преобразования строки в число! (ирония)

> Вот просто пример приведи, неважно, пускай некомпилируемый, как ты хочешь чтоб это работало...


generic
type Key_Base is (<>);
type Number is private;
type Key_Arr will be declared; -- как-то так
with function Val_Number(Expression: Key_Arr; Position: access integer; V: access Number) return boolean;
package Parser is
...



Ещё:
"Info: instantiation of SMTH during elaboration. Implicit pragma Elaborate_All for SMTH generated."

Если после with module; use module; ещё вписать pragma Elaborate_All(module), то предупреждение и счезает, но появляется ошибка о циклической элаборации. Это надо как-то обходить, или воспринимать, как изъян архитектуры модулей?

Код


error: elaboration circularity detected
info:    "winapi.strings (body)" must be elaborated before "winapi.strings (body)"
info:       reason: pragma Elaborate_All in unit "winapi.strings (body)"
info:          "winapi.strings (body)"
info:             must be elaborated along with its spec:
info:          "winapi.strings (spec)"
info:             which is withed by:
info:          "winapi (body)"
info:             which must be elaborated along with its spec:
info:          "winapi (spec)"
info:             which is withed by:
info:          "winapi.conversions (spec)"
info:             which is withed by:
info:          "winapi.strings (body)"

gnatmake: *** bind failed.


Особенно вот это место:

"winapi (spec)"
info: which is withed by:
info: "winapi.conversions (spec)"

У меня в WinAPI.Strings не написано with WinAPI.

Иерархия такая:

WinAPI
WinAPI.Strings
WinAPI.Converstions

Каждый модуль использует то и только те, что ниже него в списке.

Автор: volvo 11.03.2011 15:56

Цитата
type Key_Arr will be declared; -- как-то так
Так не пойдет. Максимум, что можно предложить:
generic
type Key_Base is (<>);
type Key_Arr is array (Positive range <>) of Key_Base;
type Number is private;
with function Val_Number(Expression: Key_Arr; Position: access integer; V: access Number) return boolean;
package Parser is
-- ...

и звать так:
   type Char_Arr is array (Positive range <>) of Character;
function My_Func (Expression : Char_Arr; Position : access Integer; V : access f80) return Boolean is
begin
-- ...
end My_Func;

package f80_Parser is new Parser(Character, Char_Arr, f80, My_Func);
use f80_Parser;

Тогда тип Key_Arr из пакета Dictionaries не нужно создавать, его можно сразу передавать в пакет, уже готовый. Понимаешь, в чем тут проблема, да? В том, что тебе для описания функции My_Func (еще до инстанцирования шаблона) нужен тип-массив. Вот в нем и проблема... В принципе, все стандартные контейнеры поступают подобным образом: получают извне и тип элементов, и тип-индекс, и тип-массив. Если бы можно было сделать так, как ты хочешь - тип-массив однозначно был бы описан внутри шаблона. Но, увы, это невозможно.

Цитата
Если после with module; use module; ещё вписать pragma Elaborate_All(module), то предупреждение и счезает, но появляется ошибка о циклической элаборации. Это надо как-то обходить, или воспринимать, как изъян архитектуры модулей?
Взял твой код, вписал туда Elaborate_All всего в двух файлах, в трех местах:

1)
with Parser; pragma Elaborate_All (Parser);
(файл func_lib.ads)
2)
with Func_Lib; pragma Elaborate_All (Func_Lib);
use Func_Lib;
with WinAPI.Bitmaps; pragma Elaborate_All (WinAPI.Bitmaps);
use WinAPI.Bitmaps;
(файл wintestmain.adb)
, и полностью пересобрал программу (то есть, совсем полностью, удалил все, что было в папке, все *.o, *.ali, *.exe и сделал Build All). Ни одного предупреждения, связанного с элаборацией больше не присутствует. Не надо во всех модулях. где были Warning-и, это делать сразу. Исправляй ошибки/предупреждения по мере их поступления. Так что никакого изъяна в архитектуре нет...

Автор: TarasBer 17.03.2011 19:21

1. От предупреждений я, вроде как, избавился. Правда, при включённой оптимизации ругается на конверсию LPARAM в PRECT. Что делать?

2. Стандартные вектора мне не понравились тем, что в них почему-то нет именно тех операций, которые мне нужны. Простейшие действия превращаются в пляски с бубном. Короче, я забил и свелосипедил.

3. В среде вкладочка Project View полезна, но как сделать так, чтобы она не показывала локальные подпрограммы в одном списке с глобальными, чтобы она иерархию подпрограмм показывала в виде дерева?

4. Если код имеет ошибки, то я вообще не понял, по какому принципу выбирается место, где они показываются, по-моему, по абсолютно случайному. Я ошибся в модуле A, компилятор показывает на ошибку в модуле B, использующем модуль A. Я поначалу долго думал, потом понял, что надо сразу свернуть все ошибки, найденный в модуле B и сразу смотреть на модуль A.

5. Напрягает, что навигация по модулям работает только после корректной компиляции проекта. А если я хочу залезть внутрь того модуля именно для того, чтобы дописать в него кое-что, что сделает проект компилирующимся? Что делать? Ааа, файл-открыть-папка вверх-папка с проектами-ещё одна папка-ой не туда, где же этот модуль-а, другая папка-о, наконец-то открыл.

6. Я так и не понял, как подружить отладочные пулы с объектами, живущими в глобальной области видимости. Ведь они умирают только при закрытии приограммы, а вывод утечек происходит до этого. Поэтому опять пришлось совершать извращение.

7. Стиль кода я не правил вообще. И делать это вручную не собираюсь. Есть автоматика для этого?

8. Как сделать программе иконку?

Пока что вышло вот это:

Прикрепленное изображение

(правда, такие приколы уж очень медленно считаются).

Прикрепленный файл  Func_Graph_Test.rar ( 28.92 килобайт ) Кол-во скачиваний: 293

Автор: volvo 18.03.2011 16:40

Цитата
1. От предупреждений я, вроде как, избавился. Правда, при включённой оптимизации ругается на конверсию LPARAM в PRECT. Что делать?
От этого предупреждения нельзя избавляться ни в коем случае (в смысле, глушить его), и просто не обращать внимания - тоже. Это может привести к серьезным проблемам. В частности, в доках на Gnat Pro приведен такой

пример (Показать/Скрыть)


Цитата
3. В среде вкладочка Project View полезна, но как сделать так, чтобы она не показывала локальные подпрограммы в одном списке с глобальными, чтобы она иерархию подпрограмм показывала в виде дерева?
Никак. Это не предусмотрено. Задача у этого окна - не показывать, какая функция в какую вложена, а быстро просмотреть, какие сущности (модули, типы, переменные) описаны в файле. Для удобства такого просмотра список сущностей просто сортируется по алфавиту. Ну, или можно озадачиться и самому написать подобное окошечко, в котором будет нужный функционал. На Python-е.

Цитата
5. Напрягает, что навигация по модулям работает только после корректной компиляции проекта.
Это то есть как? Я вот только что взял проект ,который вообще не компилировал на домашней машине, открыл его, и даже до компиляции в нем прекрасно работает навигация по модулям. Хотя, я не знаю, какой ты смысл вкладываешь в понятие навигация. То, что можно в Project View видеть все папки, связанные с проектом, и открыть любой модуль, который находится в одной из этих папок - это факт. Повторяю: еще вообще до компиляции.

Цитата
7. Стиль кода я не правил вообще. И делать это вручную не собираюсь. Есть автоматика для этого?
Естественно. Закрываешь все файлы редактора, заходишь в Tools -> Consoles -> OS Shell, и в полученном окошке набираешь команду
gnat pretty -rf F:\Programs\Ada\forum\main.adb
(со своим файлом, разумеется). Потом открываешь обработанный файл в редакторе, и смотришь на разницу... Но сначала "потренируйся на кошках" (С), у тебя есть директивы препроцессора #if/#end, я не знаю, как Pretty Printer себя с ними поведет. Без него работает прекрасно:

До:
Прикрепленное изображение

После:
Прикрепленное изображение

Остальное - чуть позже, ближе к вечеру...

Автор: -TarasBer- 18.03.2011 23:32

> Так что тебе надо либо включать pragma No_Strict_Aliasing для типа PRECT, либо в список ключей компиляции добавить -fno-strict-aliasing (я выбираю именно этот вариант), если выбрана оптимизация второго уровня и выше:

Тогда данный вид оптимизации угробится во всём проекте?
Включить прагму для одного типа я не могу, так как он определён в не моём модуле.
Может определить свой тип, логически равный PRECT, и прагму для него включить? А в обработчике WM_SIZING работать именно с ним (а конверсия эта мне нужна именно для WM_SIZING).

> Это то есть как?

Я имею в виду, прямо в коде ткнуть правой кнопкой по названию модуля, переменной, функции и выбрать "перейти к описанию/реализации".

Автор: volvo 19.03.2011 3:35

Цитата
Тогда данный вид оптимизации угробится во всём проекте?
Да. Если это нежелательно - то сделай то, что сам озвучил (можно прямо внутри процедуры Sizing):
   type P_RECT is access all RECT;
pragma No_Strict_Aliasing (P_RECT);

-- Эту функцию не забудь убрать из WinApi.Conversions
function To_PRECT is new Ada.Unchecked_Conversion(LPARAM, P_RECT);

-- ...
R: constant P_RECT := To_PRECT(lp);

, и убрать -fno-strict-aliasing, если добавлял. Предупреждение уйдет...

Цитата
8. Как сделать программе иконку?
Создаю обычный RC-файл из одной строки:

MAINICON ICON "beautifier.ico"
, потом его обрабатываю компилятором ресурсов и конвертором Resource To Object. У меня оба эти файла нашлись в \WINDOWS\Microsoft.NET\Framework\v2.0.50727 (ни в Дельфи, ни в Code::Blocks конвертора не нашлось, только rc). То есть, последовательность такая (я для простоты закинул RC вместе с иконкой в ту самую папку, .NET-овскую):

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>rc -r -dWin32 -fo bf.res bf.rc
тут бла-бла-бла, скомпилировал в RES
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>cvtres /machine:x86 /out:bf.rbj bf.res
бла-бла-бла, преобразовал в RBJ

, а теперь в любой ADS-файл, который подключается к программе, добавь строку
pragma Linker_Options ("{полный_путь_к_полученному_RBJ_файлу}\bf.rbj");

Обычно это делается в Linker_Options.ads, но я смотрю, этот файл у тебя никуда не подключается, так что туда запихивать бесполезно, иконка не изменится. Добавь строку именно в подключаемый файл. После пересборки у EXE-шника будет иконка...

М
Вопрос об исключениях перенесен:
http://forum.pascal.net.ru/index.php?showtopic=28172


Автор: Ахмед 28.05.2012 23:58

есть кто умеет писать на Аде?!! помогите, нужно найти произведение элементов одномерной матрицы

Автор: IUnknown 29.05.2012 0:37

Задание нормально поставь. Какой тип элементов массива (одномерный - это массив а не матрица)? Размер? Как задается массив (ввод от пользователя, генератор случайных чисел, константа)?

В простейшем случае будет так:

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
type Vector is array(Positive range <>) of Long_Integer;

Size : constant := 10;
Arr : Vector(1 .. Size) := (2, 3, 4, others => 5);
p : Long_Integer := 1;
begin
for i in Arr'Range loop
p := p * Arr(i);
end loop;
Put_Line ("P = " & Long_Integer'Image(p));
end Main;