Ответы пользователя по тегу Windows
  • Как создать окно OpenGL в окне полученном от CreateWindowEx (WINAPI)?

    @MarkusD
    все время мелю чепуху :)
    Использование glfw нередко приводит к тому, что обычные для OpenGL вещи средствами glfw сделать невозможно.
    В рамках glfw контекст OpenGL непосредственно объединен с окном операционной системы в типе GLFWwindow[?].
    Разделить их или использовать по отдельности уже не получится т.к. glfw не дает такого интерфейса.
    Так же, в функцию glfwCreateWindow[?] невозможно передать и дескриптор окна операционной системы если хочется создать дочернее окно в своем.

    Это такая ловушка использования glfw. Или пользователь использует glfw полностью с самого начала и мирится с ограничениями, или он отказывается от использования glfw и делает все руками.

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

    Для решения задачи более гибкого создания окон и рисования в них средствами OpenGL лучше зайти со стороны WGL[?] и прямой работы с Win32 API. В этом случае можно даже одним контекстом обойтись, привязывая его то к одному окну, то к другому на время отрисовки.

    Но если требуется просто добавить у себя элементы интерфейса в свое текущее окно, то лучше и удобнее будет взять imgui или подобную библиотеку. Для этого от glfw можно не отказываться.
    Ответ написан
    Комментировать
  • Повреждение стека вокруг переменной - как побороть?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Соглашение __stdcall обязывает пользователя функции передать параметры функции на стеке по значению, но освобождает его чистить стек после вызова. Стек от параметров чистит сама вызванная функция.

    В результате подмены сигнатуры с BOOL (__stdcall *)(HANDLE, PBOOL) на bool (__stdcall *)(void*, bool*) компилятор думает об одном размере стека, а код функции - о других.

    Поэтому сигнатуры и соглашение о вызове импортируемой функции всегда должны совпадать с объявлением этой функции в импортируемой библиотеке! Вообще всегда! Даже при условии следующего текста.

    Однако, конкретно тут проблема у нас не в несовпадении типов, потому что.
    __stdcall свой результат передает через регистр. регистр используется целочисленный или вещественный. Для целочисленного регистра используется правило продвижения типа. Это означает, что функция, записав значение типа BOOL (размер 4Б) ничего не испортит пользовательскому коду, который прочитает из регистра все 4Б с учетом правила продвижения.

    Реальная проблема кроется в том, что указатель на однобайтовое целое (bool*) передается в использование как указатель на четырехбайтовое целое (BOOL* или PBOOL). Вызываемая функция ведь имеет сигнатуру BOOL (__stdcall *)(HANDLE, PBOOL) и со вторым параметром работает как с 4Б целым по указателю.
    Именно это и приводит к порче стека и тебе, автор, сильно повезло что ты запускаешься в отладке, где каждое значение на стеке обрамлено заборчиком, за сохранностью которого всегда приглядывает специальный сервисный код между обращениями к подпрограммам.

    Именно такой заборчик рядом с isWow64 и был поломан в результате вызова IsWow64Process с параметром неподходящей длины. Измени тип isWow64 на BOOL и все станет нормально, даже хендл "kernel32.dll" потом сможешь нормально освободить.
    Ответ написан
    5 комментариев
  • Что выбрать для освоения DirectX - UWP или Win32 API?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Microsoft UWP является надстройкой для создания универсальных приложений, которые, в теории, должны легко переноситься между различными аппаратными слоями платформы Windows. UWP поддерживается только в Win10, реализована на базе расширения C++/CX стандарта C++17 и выполна преимущественно в объектном стиле.

    Windows API является низкоуровневым слоем взаимодействия между приложением и операционной системой. Win32 API поддерживается всеми версиями Windows, начиная с Windows 95. Однако, разные версии Windows поддерживают разные наборы функций. Поэтому уровень поддержки той или иной функции из набора API всегда следует уточнять в документации. Реализован Win32 API на языке C стандарта C99 и выполнен в процедурном стиле.

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

    C++/CX является расширением стандарта и не поддерживается другими платформами, а так же всеми компиляторами кроме компилятора Microsoft. При этом, существуют такие условия, когда отказаться от использования C++/CX и UWP невозможно. В иных ситуациях следует принимать к сведению особый синтаксис расширения и объектную организацию. Скажем, я бы не стал полностью весь проект делать на базе C++/CX.

    WinAPI, с другой стороны, предоставляет довольно низкоуровневый доступ, что немного осложняет реализацию требуемого функционала. Ряд абстракций, по умолчанию доступных в UWP, или потребуется сделать самому, или сделать вообще не получится без прямой низкоуровневой работы с драйверами.

    В любом случае, выбрав UWP или WinAPI, дальше тебе все равно лучше работать исключительно со стандартным C++ и стандартной реализацией DirctX для C++. От C++/CX стоит избавляться на как можно ранних слоях абстракции палатформозависимого кода. От типов и абстракций WInAPI, равно как и от наследия C99, тоже лучше избавляться как можно раньше и переходить на работу исключительно со стандартным C++.
    Ответ написан
    1 комментарий
  • Как реализовать кроссплатформенное ПО с библиотеками для 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"
    Ответ написан
  • Можно ли совместить в одном проекте программы написанные на разных языках (C++, C#) в VS2012?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    https://github.com/FrankStain/tex-conv
    Это пример такого проекта. Многозадачный конвертер текстур.

    На верхнем уровне лежит C# приложение с UI на WinForms, вся работа с пользователем выполнена именно тут.
    К верхнему уровню подключается C++/CLI ядро, представляющее собой библиотеку классов. Это ядро связывает верхний уровень с нижним, который представлен потенциально несчетным набором плагинов.

    Библиотека классов в C# используется как будто это рядовой модуль.

    Конкретно для твоего случая я порекомендую поступить так.
    • Нижний уровень - проект статической библиотеки, в которой будет весь твой C++ код.
    • Средний уровень - C++/CLI библиотека классов, в которую и линкуется нижний уровень, свяжет нижний уровень с верхним через свои классы.
    • Высокий уровень C# приложение, использующее классы среднего уровня.
    Ответ написан
    Комментировать
  • Как разделить жесткий диск на 2 раздела и сделать их с разными файловыми системами?

    @MarkusD
    все время мелю чепуху :)
    Для этих целей есть ведь гора утилит. Partition Magic и Acronis Disk Director к примеру.
    Первым я пользовался в нулевых, последним - и по сей день.
    Ответ написан
    3 комментария