Задать вопрос
  • Как реализовать кроссплатформенное ПО с библиотеками для Windows/Linux?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Я с 2011 года занимаюсь совершенствованием игрового фреймворка. Весь его код написан на C++. Целевых платформ раньше было 5 (Win, MacOs, iOs, Android, Bada), теперь 4 (Bada закрылась же) с приглядом за Tizen, WinMo и, когда-нибудь, консолями.
    В общем, уровень требований к кроссплатформенности должен быть понятен. И вот как я этого добился.

    Большая часть кода написана на платформонезависимом C++. Весь платформозависимый код расщеплен на три слоя:
    - Нижний слой, общий интерфейс для всех платформ, общие поля всех платформ.
    - Средний слой, platform-specific решения и поля. Наследуется от нижнего.
    - Верхний слой, ввод platform-spcific кода во фреймворк. Наследуется от среднего слоя.

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

    На уровне файлов этот подход работает так.
    Есть в заголовках проекта папка "platform", где собраны нижние уровни расщепления, мастер-заголовок с условным подключением среднего уровня расщепления и все общие типы для платформ.
    Так же в проекте есть папки "platform.windows", "platform.macos", "platform.###", в которых реализован средний уровень расщепления и мастер-заголовки для условного подключения.
    Верхний уровень или реализуется в своей папке, если он представляет собой целую подсистему, или описывается во все той же папке "platform".
    Исходный код сгруппирован так же, но включает в себя только мастер-заголовок .

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

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

    UPD:
    Пример с файлом очень хорошо подходит благодаря своей простоте, его я даже по памяти могу выписать из своего фреймворка, но я кое-что все таки упрощу, чтобы никого не смущать и не пугать.
    spoiler
    // PlatformSpecificFile.Windows.h
    class PlatformSpecificFile
    {
    // Platform-specific interface.
    public:
    	inline ::HANDLE GetHandle() const	{ return m_handle; };
    	
    // Platform-independent interface, but platform-dependent implementation.
    public:
    	// RAII.
    	PlatformSpecificFile() = delete;
    	PlatformSpecificFile(
    		const std::string& path,
    		const OpeningMode desired_mode,
    		const AccessOptions& desired_access,
    		const SharingOptions& desired_sharing
    	);
    	
    	virtual ~PlatformSpecificFile();
    	
    	void Close();
    	void Flush();
    	
    	const size64_t GetSize() const;
    	const bool Resize( const size64_t new_size );
    	
    	const size32_t Read( NotNull<uint8_t> buffer, const size32_t buffer_size ) const;
    	const size32_t Write( NotNull<const uint8_t> buffer, const size32_t buffer_size );
    	
    	const size64_t Seek( const size64_t offset, const SeekOrientation orientation );
    	
    	inline const bool IsValid() const	{ return IsHandleValid( m_handle ); };
    	
    private:
    	::HANDLE	m_handle = INVALID_HANDLE_VALUE;
    };
    
    // PlatformSpecificFile.Android.h
    class PlatformSpecificFile
    {
    // Platform-specific interface.
    public:
    	inline int GetHandle() const	{ return m_handle; };
    	
    // Platform-independent interface, but platform-dependent implementation.
    public:
    	// RAII.
    	PlatformSpecificFile() = delete;
    	PlatformSpecificFile(
    		const std::string& path,
    		const OpeningMode desired_mode,
    		const AccessOptions& desired_access,
    		const SharingOptions& desired_sharing
    	);
    	
    	virtual ~PlatformSpecificFile();
    	
    	void Close();
    	void Flush();
    	
    	const size64_t GetSize() const;
    	const bool Resize( const size64_t new_size );
    	
    	const size32_t Read( NotNull<uint8_t> buffer, const size32_t buffer_size ) const;
    	const size32_t Write( NotNull<const uint8_t> buffer, const size32_t buffer_size );
    	
    	const size64_t Seek( const size64_t offset, const SeekOrientation orientation );
    	
    	inline const bool IsValid() const	{ return m_handle >= 0; };
    	
    private:
    	int		m_handle = -1;
    };
    
    // File.h
    class File final : public PlatformSpecificFile
    {
    public:
    	using PlatformSpecificFile::PlatformSpecificFile;
    	
    	const size64_t GetPosition() const; // Seek( 0, SeekOrientation::FromPosition );
    	
    	const bool SetPosition( const size64_t position ); // Seek( position, SeekOrientation::FromBeginning );
    	
    	const bool IsFileEnded() const; // GetPosition() == getSize();
    };


    Мастер-заголовок платформенного кода "platform.h" в зависимости от сценария сборки включает в себя один из мастер-заголовков платформозависимого кода "platform.###.h". Платформозависимый код уже включает в себя соответствующий заголовок файла "PlatformSpecificFile.###.h"
    Ответ написан
  • Существует ли обработчик GET запросов в NODE.js?

    evgeniy2194
    @evgeniy2194
    PHP, js developer
    Комментировать
  • Куда податься со знанием python (кроме WEB)?

    @Pentblch
    Смотрю в сторону Web, начинающий
    А что интересует то?

    Тестирование, администрирование, обучения машинные и прочие исследования.

    Ответ на этот вопрос лучше найти в гугле, по вакансияv поройтесь, в яндекс вакансии посмотрите, что они для python разработчика предлагаю, варгейминг вроде тоже ищет python программистов.

    Но веб его основное, на данный момент.
    Ответ написан
    Комментировать
  • Какую выбрать среду программирования для Python?

    longclaps
    @longclaps
    Зачем, почему, какой... Это всё шашечки.
    PyCharm.
    Ответ написан
    2 комментария
  • Как оправлять команды у бота Telegram при выборе в меню?

    landergate
    @landergate
    IT-шный jack-of-all-trades
    Не пойму, как отлавливать, какую из 3х клавишей нажал?
    и как сделать так, чтобы в меню был один текст, а при нажатии на нее отправлялась к примеру команда?

    С помощью Inline Keyboards, появившемся в Bot API 2.0.
    https://core.telegram.org/bots/2-0-intro#new-inlin...
    https://core.telegram.org/bots/api#inlinekeyboardmarkup

    > Unlike with custom reply keyboards, pressing buttons on inline keyboards doesn't result in messages sent to the chat. Instead, inline keyboards support buttons that work behind the scenes: callback buttons, URL buttons and switch to inline buttons.

    Как на этапе отправки текста, мы знаем, что нам надо перевести текст?

    При приёме сообщения от user_id, бот проверяет, на каком шаге в последний раз остановился этот user_id, и обрабатывает сообщение в рамках текущего шага. Если шаг "перевести" - то в ответ на любое сообщение он переведёт строку. На этапе "перевести" бот просто не показывает никакого меню, он просто ждёт строку.

    Для этого боту делают хранилище сессий. Это может быть просто БД с колонками `user_id` и `state`, где в стэйте будет указан текущий шаг. При обработке сообщения, бот смотрит шаг и действует в соответствии с тем, чего хотел пользователь на этом шаге.
    Если пользователь запросил другую функцию, или сделал /cancel, поменять шаг в таблице.
    Ответ написан
    8 комментариев
  • Каким образом хэндлеры pyTelegramBotAPI обрабатывают входящие сообщения?

    @nllm
    Надо фиксировать состояния пользователя и в зависимости от текущего состояния производить ту или иную операцию. Тогда сможете выстраивать диалог
    Ответ написан
    Комментировать
  • PYTHON: Как удалить ряд символов из строки?

    skipirich
    @skipirich
    проходил мимо
    Я бы сделал регулярным выражением. Например строка mystr выглядит вот так asdw#df%mm!@* и надо удалить символы #%!@*, тогда
    mystr = re.sub(r"[#%!@*]", "", mystr)
    Ответ написан
    Комментировать