演练:使用 C++ 创建 SDK
本演练演示如何创建本机 C++ 数学库 SDK,将 SDK 打包为 Visual Studio 扩展 (VSIX),然后使用它创建应用。 本演练分为以下步骤:
先决条件
要按照本演练的步骤操作,必须安装 Visual Studio SDK。 有关详细信息,请参阅 Visual Studio SDK。
创建本机库和Windows 运行时库
在菜单栏上,依次选择“文件”>“新建”>“项目”。
在模板列表中,展开 Visual C++>Windows Universal,然后选择 DLL(Windows 通用应用)模板。 在 “名称 ”框中,指定
NativeMath
,然后选择“ 确定 ”按钮。更新 NativeMath.h 以匹配以下代码。
#pragma once class __declspec(dllexport) BasicMath { public: BasicMath(); double add(double firstNumber, double secondNumber); double subtract(double firstNumber, double secondNumber); };
更新 NativeMath.cpp 以匹配以下代码:
// NativeMath.cpp : Defines the exported functions for the DLL application. // #include "pch.h" #include "NativeMath.h" BasicMath::BasicMath() { } double BasicMath::add(double firstNumber, double secondNumber) { return firstNumber + secondNumber; } double BasicMath::subtract(double firstNumber, double secondNumber) { return firstNumber - secondNumber; }
在解决方案资源管理器中,打开解决方案“NativeMath”的快捷菜单,然后选择“添加新>项目”。
在模板列表中,展开 Visual C++,然后选择Windows 运行时组件模板。 在 “名称 ”框中,指定
NativeMathWRT
,然后选择“ 确定 ”按钮。更新 Class1.h 以匹配以下代码:
#pragma once namespace NativeMathWRT { public ref class BasicMathWinMD sealed { public: BasicMathWinMD(){}; double multiply(double firstNumber, double secondNumber); double divide(double firstNumber, double secondNumber); }; }
更新 Class1.cpp 以匹配以下代码:
// Class1.cpp #include "pch.h" #include "Class1.h" using namespace NativeMathWRT; using namespace Platform; double BasicMathWinMD::multiply(double firstNumber, double secondNumber) { return firstNumber * secondNumber; } double BasicMathWinMD::divide(double firstNumber, double secondNumber) { if(0 == secondNumber) return -1; return firstNumber / secondNumber; }
在菜单栏上,依次选择“生成”>“生成解决方案” 。
创建 NativeMathVSIX 扩展项目
在解决方案资源管理器中,打开解决方案“NativeMath”的快捷菜单,然后选择“添加新>项目”。
在模板列表中,展开 Visual C#>Extensibility,然后选择 VSIX 项目。 在 “名称 ”框中,指定 NativeMathVSIX,然后选择“ 确定 ”按钮。
在解决方案资源管理器中,打开 source.extension.vsixmanifest 的快捷菜单,然后选择“查看代码”。
使用以下 XML 替换现有 XML。
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011"> <Metadata> <Identity Id="NativeMathVSIX..c6b3cae1-e7e2-4e71-90f6-21017ea0dff7" Version="1.0" Language="en-US" Publisher="MyName" /> <DisplayName>Native Math SDK</DisplayName> <Description>Native Math Library w/ Windows Runtime Additions</Description> </Metadata> <Installation Scope="Global" AllUsers="true"> <InstallationTarget Id="Microsoft.ExtensionSDK" TargetPlatformIdentifier="Windows" TargetPlatformVersion="v8.0" SdkName="NativeMathSDK" SdkVersion="1.0" /> </Installation> <Dependencies> </Dependencies> <Assets> <Asset Type="Microsoft.ExtensionSDK" d:Source="File" Path="SDKManifest.xml" /> </Assets> </PackageManifest>
在解决方案资源管理器中,打开 NativeMathVSIX 项目的快捷菜单,然后选择“添加新>项”。
在 Visual C# 项列表中,展开“数据”,然后选择“XML 文件”。 在 “名称 ”框中,指定
SDKManifest.xml
,然后选择“ 确定 ”按钮。使用此 XML 替换文件的内容:
<FileList Identity = "NativeMathSDK, Version=1.0" DisplayName = "Native Math SDK" MinVSVersion = "11.0" AppliesTo = "WindowsAppContainer + (CSharp | VB | VisualC)"> <File Reference="NativeMathWRT.winmd" Implementation="NativeMathWRT.dll" /> </FileList>
在 解决方案资源管理器,在 NativeMathVSIX 项目下,创建以下文件夹结构:
\DesignTime \CommonConfiguration \Neutral \Include \Debug \x86 \Redist \Debug \x86 \References \CommonConfiguration \Neutral
在解决方案资源管理器中,打开解决方案“NativeMath”的快捷菜单,然后在文件资源管理器中选择“打开文件夹”。
在 文件资源管理器 中,复制 $SolutionRoot$\NativeMath\NativeMath.h,然后在 解决方案资源管理器 的 NativeMathVSIX 项目中,将其粘贴到 $SolutionRoot$\NativeMathVSIX\DesignTime\CommonConfiguration\Neutral\Include\ 文件夹中。
复制 $SolutionRoot$\Debug\NativeMath\NativeMath.lib,然后将其粘贴到 $SolutionRoot$\NativeMathVSIX\DesignTime\Debug\x86\ 文件夹中。
复制 $SolutionRoot$\Debug\NativeMath\NativeMath.dll 并将其粘贴到 $SolutionRoot$\NativeMathVSIX\Redist\Debug\x86\ 文件夹中。
复制 $SolutionRoot$\Debug\NativeMathWRT\NativeMathWRT.dll 并将其粘贴到 $SolutionRoot$\NativeMathVSIX\Redist\Debug\x86 文件夹中。 复制 $SolutionRoot$\Debug\NativeMathWRT\NativeMathWRT.winmd 并将其粘贴到 $SolutionRoot$\NativeMathVSIX\References\CommonConfiguration\Neutral 文件夹中。
复制 $SolutionRoot$\Debug\NativeMathWRT\NativeMathWRT.pri 并将其粘贴到 $SolutionRoot$\NativeMathVSIX\References\CommonConfiguration\Neutral 文件夹中。
在 $SolutionRoot$\NativeMathVSIX\DesignTime\Debug\x86\ 文件夹中,创建名为 NativeMathSDK.props 的文本文件,然后将以下内容粘贴到其中:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <NativeMathSDKPath>$(FrameworkSDKRoot)\..\..\UAP\v0.8.0.0\ExtensionSDKs\NativeMathSDK\1.0\</NativeMathSDKPath> <IncludePath>$(NativeMathSDKPath)DesignTime\CommonConfiguration\Neutral\Include;$(IncludePath)</IncludePath> <LibraryPath>$(NativeMathSDKPath)DesignTime\Debug\x86;$(LibraryPath)</LibraryPath> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Link> <AdditionalDependencies>NativeMath.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> </ItemDefinitionGroup> </Project>
在菜单栏上,选择“查看>其他 Windows>属性窗口”(键盘:选择 F4 键)。
在解决方案资源管理器中,选择 NativeMathWRT.winmd 文件。 在 “属性” 窗口中,将 “生成操作 ”属性更改为 “内容”,然后将 VSIX 属性中的“包含”属性更改为 True。
对 NativeMath.h 文件重复此过程。
对 NativeMathWRT.pri 文件重复此过程。
对 NativeMath.Lib 文件重复此过程。
对 NativeMathSDK.props 文件重复此过程。
在解决方案资源管理器中,选择 NativeMath.h 文件。 在 “属性” 窗口中,将 VSIX 属性中的“包含”属性更改为 True。
对 NativeMath.dll 文件重复此过程。
对 NativeMathWRT.dll 文件重复此过程。
对 SDKManifest.xml 文件重复此过程。
在菜单栏上,依次选择“生成”>“生成解决方案” 。
在解决方案资源管理器中,打开 NativeMathVSIX 项目的快捷菜单,然后在文件资源管理器中选择“打开文件夹”。
在文件资源管理器中,导航到 $SolutionRoot$\NativeMathVSIX\bin\Debug 文件夹,然后运行 NativeMathVSIX.vsix 以开始安装。
选择“ 安装 ”按钮,等待安装完成,然后打开 Visual Studio。
创建使用类库的示例应用
在菜单栏上,依次选择“文件”>“新建”>“项目”。
在模板列表中,展开 Visual C++>Windows Universal,然后选择“空白应用”。 在 “名称 ”框中,指定 NativeMathSDKSample,然后选择“ 确定 ”按钮。
在解决方案资源管理器中,打开 NativeMathSDKSample 项目的快捷菜单,然后选择“添加>引用”。
在“ 添加引用 ”对话框中的引用类型列表中,展开 “通用 Windows”,然后选择“ 扩展”。 最后,选择本机数学 SDK 检查框,然后选择“确定”按钮。
显示 NativeMathSDKSample 的项目属性。
添加引用时,将应用 NativeMathSDK.props 中定义的属性。 可以通过检查项目的配置属性的 VC++ 目录属性来验证属性是否已应用。
在解决方案资源管理器中,打开 MainPage.xaml,然后使用以下 XAML 替换其内容:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:NativeMathSDKSample" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Class="NativeMathSDKSample.MainPage" IsTabStop="false" mc:Ignorable="d"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <TextBox x:Name="FirstNumber" HorizontalAlignment="Left" Margin="327,123,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Height="84" Width="259" FontSize="48"/> <TextBox x:Name="SecondNumber" HorizontalAlignment="Left" Margin="687,123,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Height="84" Width="271" FontSize="48"/> <Button x:Name="Execute" Content="=" HorizontalAlignment="Left" Margin="478,387,0,0" VerticalAlignment="Top" Height="63" Width="332" Click="Execute_Click"/> <RadioButton Name="add" Content="Add" HorizontalAlignment="Left" Margin="273,262,0,0" VerticalAlignment="Top" GroupName="Operation" IsChecked="True"/> <RadioButton Name="subtract" Content="Subtract" HorizontalAlignment="Left" Margin="453,262,0,0" VerticalAlignment="Top" GroupName="Operation" IsChecked="False"/> <RadioButton Name="multiplyWRT" Content="Multiply(WRT)" HorizontalAlignment="Left" Margin="615,262,0,0" VerticalAlignment="Top" GroupName="Operation" IsChecked="False"/> <RadioButton Name="divideWRT" Content="Divide(WRT)" HorizontalAlignment="Left" Margin="891,262,0,0" VerticalAlignment="Top" GroupName="Operation" IsChecked="False"/> <TextBlock Name="resultText" HorizontalAlignment="Left" Margin="478,525,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="332" Height="70" FontSize="48"/> </Grid> </Page>
更新 Mainpage.xaml.h 以匹配以下代码:
// // MainPage.xaml.h // Declaration of the MainPage class. // #pragma once #include "MainPage.g.h" namespace NativeMathSDKSample { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public ref class MainPage sealed { public: MainPage(); protected: virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; virtual void Execute_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); }; }
更新 MainPage.xaml.cpp 以匹配以下代码:
// // MainPage.xaml.cpp // Implementation of the MainPage class. // #include "pch.h" #include "MainPage.xaml.h" #include <sstream> #include "NativeMath.h" using namespace NativeMathSDKSample; using namespace Platform; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Controls; using namespace Windows::UI::Xaml::Controls::Primitives; using namespace Windows::UI::Xaml::Data; using namespace Windows::UI::Xaml::Input; using namespace Windows::UI::Xaml::Media; using namespace Windows::UI::Xaml::Navigation; using namespace NativeMathWRT; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 MainPage::MainPage() { InitializeComponent(); } /// <summary> /// Invoked when this page is about to be displayed in a Frame. /// </summary> /// <param name="e">Event data that describes how this page was reached. The Parameter /// property is typically used to configure the page.</param> void MainPage::OnNavigatedTo(NavigationEventArgs^ e) { } void NativeMathSDKSample::MainPage::Execute_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) { double iFirstNumber = _wtof(FirstNumber->Text->Data()); double iSecondNumber = _wtof(SecondNumber->Text->Data()); double result = 0; BasicMathWinMD^ basicMathWinMD = ref new BasicMathWinMD(); BasicMath basicMath; if(add->IsChecked->Value == true) { result = basicMath.add(iFirstNumber, iSecondNumber); } else if(subtract->IsChecked->Value == true) { result = basicMath.subtract(iFirstNumber, iSecondNumber); } else if(multiplyWRT->IsChecked->Value == true) { result = basicMathWinMD->multiply(iFirstNumber, iSecondNumber); } else if (divideWRT->IsChecked->Value == true) { result = basicMathWinMD->divide(iFirstNumber, iSecondNumber); } std::wstringstream s; s << result; resultText->Text = ref new String(s.str().c_str()); }
选择要 运行应用的 F5 键。
在应用中,输入任意两个数字,选择一个操作,然后选择 = 该按钮。
将显示正确的结果。
本演练演示了如何创建和使用扩展 SDK 来调用Windows 运行时库和非Windows 运行时库。