Главный вопрос: хотите ли вы, чтобы ваш файл конфигурации был на каком-то полном языке Тьюринга (как, например, Python)? Если вы этого хотите, вы можете также рассмотреть возможность встраивания какого-либо другого языка сценариев (полный по Тьюрингу), такого как Guile или Lua (потому что он может восприниматься как «более простой» для использования или встраивания, чем Python; прочитайте главу о расширении и Встраивание Python ). Я не буду обсуждать это дальше (потому что другие ответы - например, Amon - подробно обсуждали это), но обратите внимание, что встраивание языка сценариев в ваше приложение является основным архитектурным выбором , который вы должны рассмотреть очень рано; Я действительно не рекомендую делать этот выбор позже!
Хорошо известным примером программы, настраиваемой с помощью «сценариев», является редактор emacs GNU (или, возможно, AutoCAD в проприетарной области); так что имейте в виду, что если вы примете сценарии, какой-то пользователь в конечном итоге будет использовать - и, возможно, злоупотреблять, с вашей точки зрения - этой возможностью, и создать сценарий из нескольких тысяч строк; следовательно, выбор достаточно хорошего языка сценариев важен.
Однако (по крайней мере, в системах POSIX) вы можете посчитать удобным включить динамический расчет файла конфигурации во время инициализации (конечно, оставляя бремя нормальной конфигурации вашему системному администратору или пользователю; на самом деле это конфигурация текст, который приходит из некоторого файла или из какой-либо команды). Для этого вы можете просто принять соглашение (и задокументировать его), что путь к файлу конфигурации, начинающийся, например, с a !
или a, |
на самом деле является командой оболочки, которую вы будете читать как конвейер . Это дает вашему пользователю возможность выбрать любой «препроцессор» или «язык сценариев», с которым он наиболее знаком.
(вам нужно доверять своим пользователям вопросы безопасности, если вы принимаете динамически вычисляемую конфигурацию)
Таким образом, в вашем коде инициализации вы main
(например) примете какой-то --config
аргумент confarg
и получите FILE*configf;
его из него. Если этот аргумент начинается с !
(то есть, если (confarg[0]=='!')
....), вы должны использовать configf = popen(confarg+1, "r");
и закрыть этот канал с pclose(configf);
. В противном случае вы бы использовали configf=fopen(confarg, "r");
и закрыли этот файл с помощью fclose(configf);
(не забудьте проверить ошибки). См. Трубу (7) , popen (3) , fopen (3) . Для приложения, написанного на Python, прочитайте о os.popen и т.д ...
(документ также для странного пользователя, желающего передать файл конфигурации с именем, !foo.config
чтобы передать, ./!foo.config
чтобы обойти popen
хитрость выше)
Кстати, такой прием - только удобство (чтобы не требовать от опытного пользователя, например, написания какого-либо сценария оболочки для генерации файла конфигурации ). Если пользователь хочет сообщить об ошибке, он должен отправить вам сгенерированный файл конфигурации ...
Обратите внимание, что вы также можете разработать свое приложение с возможностью использования и загрузки плагинов во время инициализации, например, с помощью dlopen (3) (и вам нужно доверять своему пользователю этот плагин). Опять же, это очень важное архитектурное решение (и вам нужно определить и предоставить довольно стабильный API и соглашение об этих плагинах и вашем приложении).
Для приложения, написанного на языке сценариев, такого как Python, вы также можете принять некоторый программный аргумент для eval или exec или аналогичных примитивов. Опять же, проблемы безопасности - это забота (продвинутого) пользователя.
Что касается текстового формата вашего файла конфигурации (сгенерированного или нет), я считаю, что вам в основном нужно хорошо его документировать (и выбор какого-то конкретного формата не так важен; однако я рекомендую позволить вашему пользователю иметь возможность некоторые-пропущенные комментарии внутри него). Вы можете использовать JSON (предпочтительно с некоторым JSON-парсером, принимающим и пропускающим комментарии с обычным образом //
до eol или /*
... */
...), или YAML, или XML, или INI, или ваши собственные вещи. Разбор файла конфигурации достаточно прост (и вы найдете много библиотек, связанных с этой задачей).