Практическое руководство. Использование существующего кода C++ в приложении универсальная платформа Windows

Существуют различные способы использования существующего кода C++ в проектах универсальная платформа Windows (UWP). Некоторые способы не требуют повторной компиляции кода с включенными расширениями компонентов (C++/CX) (т. е. с параметром /ZW ) и некоторые действия. Возможно, вам потребуется сохранить код в стандартной среде C++или сохранить классическую среду компиляции Win32 для некоторых кодов. Это можно сделать с помощью соответствующих вариантов архитектуры. Рассмотрим весь код, содержащий пользовательский интерфейс И типы UWP, предоставляемые вызывающим элементам C#, Visual Basic и JavaScript. Этот код должен находиться в проектах приложений Windows и среда выполнения Windows проектах компонентов. Код, который вызывается только из C++ (включая C++/CX), может находиться в проекте, который компилируется с /ZW параметром или стандартным проектом C++. Двоичный код, который не использует запрещенные API, можно использовать, связав его в виде статической библиотеки. Кроме того, вы можете упаковить его с приложением в виде содержимого и загрузить его в библиотеку DLL.

Возможно, самым простым способом запуска классической программы в среде UWP является использование технологий Desktop Bridge. Они включают в себя Desktop App Converter, который упаковывает существующее приложение в качестве приложения UWP без изменений кода. Дополнительные сведения см. в статье Мост для классических приложений.

Остальная часть этой статьи описывает перенос библиотек C++ (библиотек DLL и статических библиотек) в универсальная платформа Windows. Возможно, вам потребуется перенести код, чтобы основная логика C++ могла использоваться с несколькими приложениями UWP.

Приложения UWP выполняются в защищенной среде. В результате многие вызовы API Win32, COM и CRT, которые могут нарушить безопасность платформы, запрещены. Параметр /ZW компилятора может обнаруживать такие вызовы и создавать ошибку. Вы можете использовать комплект сертификации приложений в приложении для обнаружения кода, вызывающего запрещенные API. Дополнительные сведения см. в разделе Тесты комплекта сертификации приложений для Windows.

Если исходный код доступен для библиотеки, можно попытаться устранить запрещенные вызовы API. Список api, которые не разрешены, см. в разделе API Win32 и COM для приложений UWP и функций CRT, которые не поддерживаются в универсальная платформа Windows приложениях. Некоторые альтернативные решения можно найти в статье Альтернативы Windows API для приложений среды выполнения Windows.

Если вы просто пытаетесь добавить ссылку из универсального проекта Windows в классическую классическую библиотеку, вы получите сообщение об ошибке, которое говорит, что библиотека несовместима. Если это статическая библиотека, вы можете связаться с библиотекой, добавив библиотеку (.lib файл) в входные данные компоновщика, так же, как и в классическом приложении Win32. Если доступна только двоичная библиотека, это единственный вариант. Статическая библиотека связана с исполняемым файлом приложения. Однако библиотеку DLL Win32, которую вы используете в приложении UWP, необходимо упаковать в приложение, включив его в проект и помечая его как содержимое. Чтобы загрузить библиотеку DLL Win32 в приложении UWP, необходимо также вызвать LoadPackagedLibrary вместо LoadLibrary него или LoadLibraryEx.

Если у вас есть исходный код библиотеки DLL или статической библиотеки, его можно перекомпилировать как проект UWP с помощью параметра компилятора /ZW . Затем вы можете добавить ссылку на нее с помощью Обозреватель решений и использовать ее в приложениях UWP на C++. Связывание библиотеки DLL с помощью библиотеки экспорта.

Чтобы сделать функциональные возможности доступными вызывающим объектам на других языках, библиотеку можно преобразовать в компонент среды выполнения Windows. среда выполнения Windows компоненты отличаются от обычных библиотек DLL, в том, что они включают метаданные в виде .winmd файлов, описывающих содержимое таким образом, чтобы требуются потребители .NET и JavaScript. Чтобы предоставить элементы API другим языкам, можно добавить конструкции C++/CX, такие как классы ссылок, и сделать их общедоступными. В Windows 10 и более поздних версий мы рекомендуем библиотеку C++/WinRT вместо C++/CX.

Предыдущее обсуждение не относится к com-компонентам, которые должны обрабатываться по-другому. Если у вас есть COM-сервер в EXE или DLL, его можно использовать в универсальном проекте Windows. Упаковайте его в качестве компонента COM без регистрации, добавьте его в проект в виде файла содержимого и создайте его с помощьюCoCreateInstanceFromApp. Дополнительные сведения см. в статье Использование DLL без COM в проекте C++ для Магазина Windows.

Если вы хотите перенести существующую com-библиотеку в UWP, ее также можно преобразовать в компонент среда выполнения Windows. Мы рекомендуем библиотеку C++/WinRT для таких портов, но также можно использовать библиотеку шаблонов среда выполнения Windows C++ (WRL). WRL устарел, и он не поддерживает все функции ATL и OLE. Зависит ли такой порт от функций COM, ATL и OLE, необходимых компоненту.

Независимо от выбранного сценария разработки следует учитывать ряд определений макросов. Эти макросы можно использовать в коде для условной компиляции кода в классическом классическом приложении Win32 и UWP.

#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP)
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)

Эти операторы могут применяться соответственно к приложениям UWP, приложениям Магазина Windows Phone, к обоим видам приложений или ни к одному из них (то есть, только к классическим приложениям Win32). Эти макросы доступны только в Windows SDK 8.1 и более поздних версий.

В этой статье содержатся следующие процедуры:

Использование DLL-библиотеки Win32 в приложении UWP

Для повышения безопасности и надежности универсальные приложения Windows выполняются в ограниченной среде выполнения. Вы не можете просто использовать собственную библиотеку DLL так, как вы будете использовать классическое классическое приложение Windows. Исходный код для библиотеки DLL можно перенести для выполнения на платформе UWP. Сначала следует изменить несколько параметров проекта и метаданных файла проекта, чтобы определять проект как проект UWP. Код библиотеки будет перекомпилироваться с помощью /ZW параметра, который включает C++/CX. Некоторые вызовы API не допускаются в приложениях UWP из-за более строгих элементов управления, связанных с этой средой. Дополнительные сведения см. в разделе API Win32 и COM для приложений UWP.

При наличии собственной библиотеки DLL, которая экспортирует функции с помощью __declspec(dllexport), эти функции можно вызывать из приложения UWP путем повторной компиляции библиотеки DLL как проекта UWP. Например, предположим, что у нас есть проект DLL Win32 с именем Giraffe , который экспортирует несколько классов и их методов с кодом, как в следующем файле заголовка:

// giraffe.h
// Define GIRAFFE_EXPORTS when building this DLL
#pragma once

#ifdef GIRAFFE_EXPORTS
#define GIRAFFE_API __declspec(dllexport)
#else
#define GIRAFFE_API
#endif

GIRAFFE_API int giraffeFunction();

class Giraffe
{
    int id;
        Giraffe(int id_in);
    friend class GiraffeFactory;

public:
    GIRAFFE_API int GetID();
};

class GiraffeFactory
{
    static int nextID;

public:
    GIRAFFE_API GiraffeFactory();
    GIRAFFE_API static int GetNextID();
    GIRAFFE_API static Giraffe* Create();
};

И следующий файл кода:

// giraffe.cpp
#include "pch.h"
#include "giraffe.h"

Giraffe::Giraffe(int id_in) : id(id_in)
{
}

int Giraffe::GetID()
{
    return id;
}

int GiraffeFactory::nextID = 0;

GiraffeFactory::GiraffeFactory()
{
    nextID = 0;
}

int GiraffeFactory::GetNextID()
{
    return nextID;
}

Giraffe* GiraffeFactory::Create()
{
    return new Giraffe(nextID++);
}

int giraffeFunction();

Все остальное в проекте (pch.h, dllmain.cpp) является частью стандартного шаблона проекта Win32. Код определяет макрос GIRAFFE_API, который разрешается при __declspec(dllexport)GIRAFFE_EXPORTS определении. То есть он определяется, когда проект создается в виде библиотеки DLL, но не когда клиент использует giraffe.h заголовок. Эту библиотеку DLL можно использовать в проекте UWP без изменения исходного кода. Необходимо изменить только некоторые параметры и свойства проекта.

Следующая процедура применяется при наличии собственной библиотеки DLL, которая предоставляет функции с помощью __declspec(dllexport).

Перенос собственной библиотеки DLL на UWP без создания нового проекта

  1. Откройте проект DLL в Visual Studio.

  2. Откройте окно свойств проекта для проекта DLL и задайте свойству Конфигурация значение Все конфигурации.

  3. В свойствах проекта на вкладке C/C++>Общие установите значение Да (/ZW) для параметра Использовать расширение среды выполнения Windows. Это свойство включает расширения компонентов (C++/CX).

  4. В Обозреватель решений выберите узел проекта, откройте контекстное меню и выберите "Выгрузить проект". Затем откройте контекстное меню узла выгруженного проекта и выберите команду редактирования файла проекта. Найдите элемент WindowsTargetPlatformVersion и замените его на следующие элементы.

    <AppContainerApplication>true</AppContainerApplication>
    <ApplicationType>Windows Store</ApplicationType>
    <WindowsTargetPlatformVersion>10.0.10156.0</WindowsTargetPlatformVersion>
    <WindowsTargetPlatformMinVersion>10.0.10156.0</WindowsTargetPlatformMinVersion>
    <ApplicationTypeRevision>10.0</ApplicationTypeRevision>
    

    .vcxproj Закройте файл, снова откройте контекстное меню и нажмите кнопку "Перезагрузить проект".

    Теперь обозреватель решений идентифицирует проект как универсальный проект Windows.

  5. Убедитесь, что файл предкомпилированного заголовка имеет правильное имя. В разделе "Предварительно скомпилированные заголовки" может потребоваться изменить предварительно скомпилированные файлы заголовков на pch.hstdafx.h другой, если вы увидите ошибку, например следующую:

    ошибка C2857: инструкция "#include", указанная с параметром /Ycpch.h командной строки, не найдена в исходном файле

    Проблема заключается в том, что старые шаблоны проектов используют другое соглашение об именовании для предварительно скомпилированного файла заголовка. Используются проекты Visual Studio 2019 и более поздних версий pch.h.

  6. Выполните сборку проекта. Вы можете получить некоторые ошибки о несовместимых параметрах командной строки. Например, нерекомендуемый сейчас, но часто используемый ранее параметр Включить минимальное перестроение (/Gm) задан по умолчанию во многих старых проектах C++ и не совместим с параметром /ZW.

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

  7. Чтобы использовать библиотеку DLL в приложении UWP в том же решении, откройте контекстное меню узла проекта UWP и выберите Добавить>Ссылка.

    В разделе Проекты>Решение установите флажок для проекта DLL и нажмите кнопку ОК.

  8. Включите файлы заголовков библиотеки в файл приложения pch.h UWP.

    #include "..\Giraffe\giraffe.h"
    
  9. Обычным способом добавьте код в проекте UWP, чтобы вызывать функции и создавать типы из библиотеки DLL.

    MainPage::MainPage()
    {
        InitializeComponent();
        GiraffeFactory gf;
        Giraffe* g = gf.Create();
        int id = g->GetID();
    }
    

Использование собственной статической библиотеки C++ в приложении UWP

Собственную статическую библиотеку C++ можно использовать в проекте UWP, однако существуют некоторые ограничения, которые необходимо принимать во внимание. Начните с изучения раздела о статических библиотеках C++/CX. Доступ к машинному коду в статической библиотеке можно выполнить из приложения UWP, однако в такой библиотеке не рекомендуется создавать открытые ссылочные типы. При компиляции статической библиотеки с параметром /ZW библиотекарь (фактически скрытый компоновщик) выводит следующее предупреждение:

LNK4264: архивирует объектный файл, скомпилированный с параметром /ZW, в статическую библиотеку; обратите внимание, что при создании типов среды выполнения Windows не рекомендуется привязка к статической библиотеке, содержащей метаданные среды выполнения Windows

Однако вы можете использовать статическую библиотеку в приложении UWP без повторной компиляции./ZW Библиотека не может объявлять типы ссылок или использовать конструкции C++/CX. Но если ваша цель заключается только в использовании библиотеки машинного кода, это можно сделать, выполнив следующие действия.

Использование собственной статической библиотеки C++ в проекте UWP

  1. В разделе свойств проекта UWP в области слева последовательно выберите Свойства конфигурации>Компоновщик>Ввод. В области справа добавьте путь к библиотеке в свойстве Дополнительные зависимости. Например, для библиотеки в проекте, в которую помещает выходные данные <SolutionFolder>\Debug\MyNativeLibrary\MyNativeLibrary.lib, добавьте относительный путь Debug\MyNativeLibrary\MyNativeLibrary.lib.

  2. Добавьте инструкцию include, чтобы ссылаться на файл pch.h заголовка (при наличии) или в любом .cpp файле по мере необходимости, и начать добавление кода, использующего библиотеку.

    #include "..\MyNativeLibrary\MyNativeLibrary.h"
    

    Не добавляйте ссылку на узел "Ссылки" в Обозреватель решений. Этот механизм работает только для компонентов среды выполнения Windows.

Перенос библиотеки C++ в компонент среды выполнения Windows

Предположим, вы хотите использовать собственные API в статической библиотеке из приложения UWP. Если у вас есть исходный код для собственной библиотеки, можно перенести код в компонент среда выполнения Windows. Она больше не будет статической библиотекой; Вы превратите его в библиотеку DLL, которую можно использовать в любом приложении UWP на C++. В этой процедуре описывается создание нового компонента среда выполнения Windows, использующего расширения C++/CX. Дополнительные сведения о создании компонента, использующего C++/WinRT, см. в среда выполнения Windows компонентах C++/WinRT.

При использовании C++/CX можно добавлять типы ссылок и другие конструкции C++/CX, которые доступны клиентам в любом коде приложения UWP. Эти типы можно получить из C#, Visual Basic или JavaScript. Ниже описываются основные действия.

  • Создание проекта компонента среда выполнения Windows (универсального windows)
  • скопируйте код для статической библиотеки в него и
  • Устраняйте все ошибки компилятора, вызванные параметром /ZW .

Перенос библиотеки C++ в компонент среды выполнения Windows

  1. Создайте проект компонента среда выполнения Windows (универсальная версия Windows).

  2. Закройте проект.

  3. В проводник Windows найдите новый проект. Затем найдите проект библиотеки C++, содержащий код, который требуется перенести. Скопируйте исходные файлы (файлы заголовков, файлы кода и любые другие ресурсы, в том числе в подкаталогах) из проекта библиотеки C++. Вставьте их в новую папку проекта, сохранив одну и ту же структуру папок.

  4. Откройте проект компонента среда выполнения Windows. Откройте контекстное меню узла проекта в Обозреватель решений и выберите "Добавить>существующий элемент".

  5. Выберите все файлы, которые будут добавлены из исходного проекта, и нажмите кнопку ОК. При необходимости повторите эти действия для вложенных папок.

  6. На этом этапе может появиться повторяющийся код. Если есть несколько предварительно скомпилированных заголовков (например, оба stdafx.h и pch.h), выберите один, чтобы сохранить. В него скопируйте необходимый код, например выражения include. Затем удалите другой файл и в свойствах проекта в разделе Предварительно скомпилированные заголовки убедитесь, что имя файла заголовка правильно.

    Если файл был изменен для использования в качестве предкомпилированного заголовка, убедитесь в правильности параметров предкомпилированных заголовков для каждого файла. Выберите каждый .cpp файл, в свою очередь, откройте его окно свойств и убедитесь, что для всех задано значение Use (/Yu),за исключением предварительно скомпилированного заголовка, который должен быть задан как Create (/Yc).

  7. Постройте проект и устраните все ошибки. Эти ошибки могут быть вызваны с помощью /ZW параметра или могут быть вызваны новой версией пакета SDK для Windows. Кроме того, они могут отражать зависимости, такие как файлы заголовков, от которые зависит библиотека, или различия в параметрах проекта между старым проектом и новым.

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

  9. Протестируйте компонент, добавив ссылку на него из проекта приложения UWP, и добавьте код для вызова созданных открытых API.

См. также

Перенос на универсальную платформу Windows