Pull to refresh

System.Console, Mono и NCurses

Reading time2 min
Views4.9K
Всем привет, в своей работе (а ранее и в учебе) я часто использую C# и этот язык стал мне, что называется, привычным. Решив немного потренироваться в программировании, я написал консольный текстовый редактор для Linux. Вкратце опишу полученный опыт.

В Mono класс System.Console поддерживается не полностью, но Mono замечателен тем, что также как и в .NET можно использовать P/Invoke, для вызова методов нативных C/C++ Linux библиотек.

В моем случае это была библиотека ncurses. Выглядит это так:

public class Curses
    {        
        /// <summary>
        /// файл подключаемой библиотеки
        /// </summary>
        const string NCurses = "libncursesw.so.5";
        /// <summary>
        /// указатель на окно терминала
        /// </summary>
        private IntPtr window;
        [DllImport(NCurses)]
        private extern static IntPtr initscr();
        /// <summary>
        /// конструктор класса обертки
        /// </summary>
        public Curses()
        {
            window = initscr();
        }
        [DllImport(NCurses)]
        private extern static int endwin();
        /// <summary>
        /// Деструктор обертки
        /// </summary>
        ~Curses()
        {
            int result = endwin();
        }
        [DllImport(NCurses)]
        private extern static int mvwprintw(IntPtr window, int y, int x, string message);
        /// <summary>
        /// Вывод сообщения по координатам
        /// </summary>
        public int Print(int x, int y, string message)
        {
            return mvwprintw(window, y, x, message);
        }
        [DllImport(NCurses)]
        private extern static int refresh(IntPtr window);
        /// <summary>
        /// Обновление окна терминала
        /// </summary>
        public int Refresh()
        {
            return refresh(window);
        }
	. . .

Все методы ncurses в этом проекте подключались по мере необходимости, в случае если System.Console работал не должным образом, но если же стандартный метод работал это значительно облегчало жизнь.

Например метод ncurses wgetch() получает два байта вместо одного для символов Юникода, и для кириллической раскладки мне пришлось бы использовать более сложный метод с передачей указателя. Использование стандартного Console.ReadKey позволило оставить весь код управляемым и легко разделить функциональные клавиши от текстовых символов.

С чтением и записью файлов также не возникло проблем и все работало штатно как и на .NET

image

Когда уже все стабильно работало, была предпринята попытка собрать этот блокнот на Windows. Дабы не собирать PDCurses из исходников, я взял готовую dll из состава MinGW, а именно libpdcursesw.dll и она хорошо справилась в качестве замены ncurses.

Для сборки блокнота мне даже не понадобился Mono, я просто открыл решение MonoDevelop в Visual Studio без всяких приключений.

Единственное что потребовало корректировки, это вывод в консоль, мне пришлось отказаться от mvwprintw и я переписал Print, вывод заработал а изменения в коде были минимальны:

public void Print(int x, int y, string message)
        {
            Console.SetCursorPosition(x, y);
            Console.Write(message);            
        }

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

Все это убедило меня в том, что C# вполне годится для задач под Linux и решения в случае чего легко портировать на Windows.

Полная реализация доступна на GitHub, ветка master для Linux и windows для Windows.
Tags:
Hubs:
Total votes 14: ↑9 and ↓5+4
Comments18

Articles