使用 C++/WinRT 创作 API
如果 API 位于 Windows 命名空间中
这是你使用 Windows 运行时 API 最常见的情况。 对于元数据中定义的 Windows 命名空间中的每个类型,C++/WinRT 都定义了 C++ 友好等效项(称为投影类型 )。 投影类型具有与 Windows 类型相同的完全限定名称,但使用 C++ 语法放置于 C++ winrt 命名空间中。 例如,Windows::Foundation::Uri 作为 winrt::Windows::Foundation::Uri 投影到 C++/WinRT。
以下是一个简单的代码示例。 若要将以下代码示例直接复制并粘贴到 Windows 控制台应用程序 (C++/WinRT) 项目的主源代码文件中,请先在项目属性中设置“不使用预编译的标头” 。
// main.cpp
#include <winrt/Windows.Foundation.h>using namespace winrt;
using namespace Windows::Foundation;int main()
{winrt::init_apartment();Uri contosoUri{ L"http://www.contoso.com" };Uri combinedUri = contosoUri.CombineUri(L"products");
}
包含的标头 winrt/Windows.Foundation.h 是 SDK 的一部分,可在文件夹 %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt\ 内找到。 该文件夹中的标头包含投影到 C++/WinRT 中的 Windows 命名空间类型。 在此示例中,winrt/Windows.Foundation.h 包含 winrt::Windows::Foundation::Uri ,它是运行时类 Windows::Foundation::Uri 的投影类型。
提示
如果希望使用来自 Windows 命名空间的类型,请包括与该命名空间对应的 C++/WinRT 标头。 using namespace 指令是可选的,不过这种指令很方便。
在上述代码示例中,在初始化 C++/WinRT 后,我们将通过其公开记录的构造函数之一(本示例中为 Uri(字符串) )堆叠分配 winrt::Windows::Foundation::Uri 投影类型的值。 这是最常见的用例,也是一般情况下你所要做的全部工作。 在有了 C++/WinRT 投影类型值后,你可以将其视为实际 Windows 运行时类型的实例,因为它具有所有相同的成员。
事实上,该投影值是一个代理;它本质上只是支持对象的智能指针。 投影值的构造函数调用 RoActivateInstance 来创建 Windows 运行时支持类(本例中为 Windows.Foundation.Uri )的实例,并将该对象的默认接口存储在新投影值内。 如下所示,你对投影值的成员的调用实际上通过智能指针代理给支持对象;这是发生状态变化的地方。

当 contosoUri 值超出范围时,它将自行销毁,并将其引用发布到默认接口。 如果该引用是对支持 Windows 运行时 Windows.Foundation.Uri 对象的最后一个引用,支持对象也会自行销毁。
提示
投影类型 是出于使用运行时类的 API 针对运行时类的包装器。 投影接口 是针对 Windows 运行时接口的包装器。
C++/WinRT 投影标头
若要使用 C++/WinRT 的 Windows 命名空间 API,你应使用来自 %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt 文件夹的标头。 下级命名空间中的类型在其直接父命名空间中引用类型是很常见的。 因此,每个 C++/WinRT 投影标头将自动包括其父命名空间标头文件;因此你不需要 明确包括它。 不过,这样做也不会出现错误。
例如,对于 Windows::Security::Cryptography::Certificates 命名空间,等效的 C++/WinRT 类型定义驻留在 winrt/Windows.Security.Cryptography.Certificates.h 中。 Windows::Security::Cryptography::Certificates 中的类型需要父 Windows::Security::Cryptography 命名空间中的类型;该命名空间中的类型可能需要其自己的父 Windows::Security 中的类型。
因此,当你包括 winrt/Windows.Security.Cryptography.Certificates.h 时,该文件反之将包括 winrt/Windows.Security.Cryptography.h;且 winrt/Windows.Security.Cryptography.h 将包括 winrt/Windows.Security.h。 这就是跟踪停止的位置,因为没有 winrt/Windows.h。 此可传递包含过程在第二级命名空间停止。
此过程间接包括为在父命名空间中定义的类提供必要的声明 和实现 的标头文件。
一个命名空间中类型的成员可以引用其他无关命名空间中的一个或多个类型。 为了让编译器能够成功编译这些成员定义,编译器需要查看所有这些类型关闭的类型声明。 因此,每个 C++/WinRT 投影标头均包括它需要声明 任何依赖类型的命名空间标头。 与父命名空间不同,此过程不 拉入所引用类型的实现 。
重要
当你希望实际使用 在无关命名空间中声明的类型(实例化、调用方法等)时,你必须包括该类型的相应的命名空间标头文件。 仅自动包括声明 ,没有实现 。
例如,如果你仅包括 winrt/Windows.Security.Cryptography.Certificates.h,则会导致声明从这些命名空间(等等,间接)拉入。
- Windows.Foundation
- Windows.Foundation.Collections
- Windows.Networking
- Windows.Storage.Streams
- Windows.Security.Cryptography
换言之,某些 API 在你包括的标头中进行了前向声明。 但它们的定义在你尚未包括的标头中。 因此,如果你随后调用 Windows::Foundation::Uri::RawUri ,那么你会收到指示成员未定义的链接器错误。 解决方法是明确 #include <winrt/Windows.Foundation.h>。 一般情况下,当你看到此类链接器错误时,应包括为该 API 的命名空间命名的标头,并重新生成。
通过对象、接口或通过 ABI 访问成员
使用 C++/WinRT 投影,Windows 运行时类的运行时表示形式将只是基础 ABI 接口。 不过,为方便起见,你可以通过类作者预期的方式根据类编码。 例如,你可以调用 Uri 的 ToString 方法,就像它是该类的方法(实际上,再深入一层,它是单独的 IStringable 接口上的方法)。
WINRT_ASSERT 是宏定义,并且扩展到 _ASSERTE。
Uri contosoUri{ L"http://www.contoso.com" };
WINRT_ASSERT(contosoUri.ToString() == L"http://www.contoso.com/"); // QueryInterface is called at this point.
这种便利是通过对相应接口的查询实现的。 不过始终在你的控制范围内。 你可以通过自己检索 IStringable 接口并直接使用它来放弃一点便利,从而提高一点性能。
在下方的代码示例中,你在运行时获取实际的 IStringable 接口指针(通过一次性查询)。 此后,你对 ToString 的调用是直接的,并且避免进一步调用 QueryInterface。
...
IStringable stringable = contosoUri; // One-off QueryInterface.
WINRT_ASSERT(stringable.ToString() == L"http://www.contoso.com/");
如果你知道你将在同一个接口调用多个方法,你可能会选择使用此技巧。
顺便说一下,如果你确实希望访问 ABI 级别的成员,那么你可以这样做。
下方的代码示例显示了如何操作,实现 C++/WinRT 与 ABI 之间的互操作中还提供了更多详细信息和代码示例。
#include <Windows.Foundation.h>
#include <unknwn.h>
#include <winrt/Windows.Foundation.h>
using namespace winrt::Windows::Foundation;int main()
{winrt::init_apartment();Uri contosoUri{ L"http://www.contoso.com" };int port{ contosoUri.Port() }; // Access the Port "property" accessor via C++/WinRT.winrt::com_ptr<ABI::Windows::Foundation::IUriRuntimeClass> abiUri{contosoUri.as<ABI::Windows::Foundation::IUriRuntimeClass>() };HRESULT hr = abiUri->get_Port(&port); // Access the get_Port ABI function.
}
延迟初始化
在 C++/WinRT 中,每个投影的类型都有一个特殊的 C++/WinRT std::nullptr_t 构造函数。 除了该构造函数,所有其他投影类型的构造函数(包括默认的构造函数)都会导致系统创建一个支持的 Windows 运行时对象,并为你提供它的智能指针。 因此,该规则适用于使用默认构造函数的任何地方,例如未初始化的本地变量、未初始化的全局变量以及未初始化的成员变量。
另一方面,如果你想要构造投影类型的变量,而无需它反过来构造支持的 Windows 运行时对象(以便你可以延迟该工作),你可以这样做。 使用该特殊 C++/WinRT std::nullptr_t 构造函数(C++/WinRT 投影已将它插入每个运行时类中)声明你的变量或字段。
在下面的代码示例中,我们将该特殊构造函数与 m_gamerPicBuffer 配合使用。
#include <winrt/Windows.Storage.Streams.h>
using namespace winrt::Windows::Storage::Streams;#define MAX_IMAGE_SIZE 1024struct Sample
{void DelayedInit(){//分配实际缓冲区,延迟初始化m_gamerPicBuffer = Buffer(MAX_IMAGE_SIZE);}private:Buffer m_gamerPicBuffer{ nullptr };//使用该特殊 C++/WinRT std::nullptr_t 构造函数(C++/WinRT 投影已将它插入每个运行时类中)声明你的变量或字段
};int main()
{winrt::init_apartment();Sample s;// ...s.DelayedInit();
}
除 std::nullptr_t 构造函数以外的投影类型上的所有构造函数都将导致创建后备 Windows 运行时对象。 std::nullptr_t 构造函数本质上不执行任何操作。 它预期投影对象会在后续时间初始化。 因此,不论运行时类是否具有默认的构造函数,你都可以使用此技巧实现有效的延迟初始化。
此注意事项会影响在其中调用默认构造函数的其他位置(如在向量和映射中)。
请考虑此代码示例,对它需要“空白应用(C++/WinRT)” 项目。
std::map<int, TextBlock> lookup;
lookup[2] = value;
进行分配会创建新 TextBlock ,然后立即使用 value 覆盖它。 下面是补救措施。
std::map<int, TextBlock> lookup;
lookup.insert_or_assign(2, value);
另请参阅默认构造函数如何影响集合。
不要错误地延迟初始化
请注意不要错误地调用 std:: nullptr_t 构造函数。 编译器的冲突解决偏向于它而非工厂构造函数。 例如,请考虑这两个运行时类定义。
idl
// GiftBox.idl
runtimeclass GiftBox
{GiftBox();
}// Gift.idl
runtimeclass Gift
{Gift(GiftBox giftBox); // You can create a gift inside a box.
}
假设我们想要构造一个不在盒子内的 Gift(使用未初始化的 GiftBox 构造的 Gift)。 首先,让我们看看错误的做法。 我们知道有一个接受 GiftBox 的 Gift 构造函数。 但是,如果想要传递 null GiftBox(通过统一初始化调用 Gift 构造函数,如下所示),则不会获得我们想要的结果 。
// These are *not* what you intended. Doing it in one of these two ways
// actually *doesn't* create the intended backing Windows Runtime Gift object;
// only an empty smart pointer.Gift gift{ nullptr };
auto gift{ Gift(nullptr) };
在此处得到的是一个未初始化的 Gift。 你无法通过未初始化的 GiftBox 得到 Gift。 下面是正确 的做法。
// Doing it in one of these two ways creates an initialized
// Gift with an uninitialized GiftBox.Gift gift{ GiftBox{ nullptr } };
auto gift{ Gift(GiftBox{ nullptr }) };
在不正确的示例中,传递 nullptr 文本会以有利于延迟初始化构造函数的方式解析。 若要以有利于工厂构造函数的方式解析,参数的类型必须是 GiftBox。 仍然可以选择传递一个显式延迟初始化 GiftBox,如正确的示例中所示。
下一个示例也正确 ,因为参数的类型为 GiftBox,而不是 std:: nullptr_t。
GiftBox giftBox{ nullptr };
Gift gift{ giftBox }; // Calls factory constructor.
仅当传递 nullptr 文本时才会引起多义性。
不要错误地复制构造。
此警告类似于上面的不要错误地延迟初始化部分中所述的警告。
除了该延迟初始化构造函数之外,C++/WinRT 投影也会将复制构造函数注入到每个运行时类中。 它是一个单参数构造函数,接受与所构造对象相同的类型。 生成的智能指针指向其构造函数参数指向的同一后备 Windows 运行时对象。 结果是两个智能指针对象指向同一后备对象。
下面是我们将在代码示例中使用的运行时类定义。
idl
// GiftBox.idl
runtimeclass GiftBox
{GiftBox(GiftBox biggerBox); // You can place a box inside a bigger box.
}
假设我们想要在一个较大的 GiftBox 内构造 GiftBox。
GiftBox bigBox{ ... };// These are *not* what you intended. Doing it in one of these two ways
// copies bigBox's backing-object-pointer into smallBox.
// The result is that smallBox == bigBox.GiftBox smallBox{ bigBox };
auto smallBox{ GiftBox(bigBox) };
正确的做法是显式调用激活工厂。
GiftBox bigBox{ ... };// These two ways call the activation factory explicitly.GiftBox smallBox{winrt::get_activation_factory<GiftBox, IGiftBoxFactory>().CreateInstance(bigBox) };
auto smallBox{winrt::get_activation_factory<GiftBox, IGiftBoxFactory>().CreateInstance(bigBox) };
如果在 Windows 运行时组件中实现此 API
无论你是自行创作该组件,还是该组件来自供应商,本部分均适用。
在应用程序项目中,引用 Windows 运行时组件的 Windows 运行时元数据 (.winmd) 文件,然后生成。 在生成过程中,cppwinrt.exe 工具生成标准 C++ 库,该库全面描述(或投影)该组件的 API 接口。 换言之,生成的库包含该组件的投影类型。
然后,与 Windows 命名空间类型一样,你只需包含标头并通过其构造函数之一构造投影类型。 应用程序项目的启动代码注册运行时类,然后投影类型的构造函数调用 RoActivateInstance 来激活引用组件中的运行时类。
#include <winrt/ThermometerWRC.h>struct App : implements<App, IFrameworkViewSource, IFrameworkView>
{ThermometerWRC::Thermometer thermometer;...
};
如果在使用的项目中实现 API
本部分中的代码示例摘自 XAML 控件;绑定到 C++/WinRT 属性主题。 请查看该主题了解更多详细信息、代码和演练,其中该演练描述了使用在采用它的同一项目中实现的运行时类的情况。
通过 XAML UI 使用的类型必须为运行时类,即使其位于与 XAML 相同的项目中。 在这种情况下,从运行时类的 Windows 运行时元数据 (.winmd) 中生成一个投影类型。 同样,你还可包含一个标头,但随后可选择 C++/WinRT 版本 1.0 或版本 2.0 方法来构造该运行时类的实例。 版本 1.0 方法使用 winrt::make;版本 2.0 方法被称作统一构造。 让我们来逐一查看。
使用 winrt::make 进行构造
让我们从默认方法(C++/WinRT 版本 1.0)开始,因为最好至少要熟悉该模式。 通过其 std::nullptr_t 构造函数构造投影类型。 该构造函数不执行任何初始化,所以你接下来必须通过 winrt::make 帮助程序函数向该实例分配一个值,同时传递任何必要的构造函数参数。 在使用代码的同一项目中实现的运行时类无需进行注册,且无需通过 Windows 运行时/COM 激活进行实例化。
有关完整演练,请参阅 XAML 控件;绑定到 C++/WinRT 属性。 本部分显示了摘自该演练的内容。
// MainPage.idl
import "BookstoreViewModel.idl";
namespace Bookstore
{runtimeclass MainPage : Windows.UI.Xaml.Controls.Page{BookstoreViewModel MainViewModel{ get; };}
}// MainPage.h
...
struct MainPage : MainPageT<MainPage>
{...private:Bookstore::BookstoreViewModel m_mainViewModel{ nullptr };
};
...// MainPage.cpp
...
#include "BookstoreViewModel.h"MainPage::MainPage()
{m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();//通过 winrt::make 帮助程序函数向该实例分配一个值,同时传递任何必要的构造函数参数。
...
}
统一构造
在 C++/WinRT 版本 2.0 及更高版本中,有一种优化的构造形式可供你使用,它被称作“统一构造”(请参见 C++/WinRT 2.0 中的新增功能和更改)。
有关完整演练,请参阅 XAML 控件;绑定到 C++/WinRT 属性。 本部分显示了摘自该演练的内容。
若要使用统一构造而不是 winrt::make,你需要一个激活工厂。 要生成激活工厂,一种好的方式是向 IDL 添加构造函数。
// MainPage.idl
import "BookstoreViewModel.idl";
namespace Bookstore
{runtimeclass MainPage : Windows.UI.Xaml.Controls.Page{MainPage();BookstoreViewModel MainViewModel{ get; };}
}
然后,在 MainPage.h 中声明和初始化 m_mainViewModel;此操作只需一步,如下所示。
// MainPage.h
...
struct MainPage : MainPageT<MainPage>
{...private:Bookstore::BookstoreViewModel m_mainViewModel;...};
}
...
接下来,在 MainPage.cpp 中的 MainPage 构造函数中,无需使用代码 m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();。
有关统一构造的详细信息,请参阅选择加入统一构造和直接实现访问。
实例化和返回投影类型和接口
以下投影类型和实例的示例可能类似于使用的项目。 请记住,投影类型(如此示例中的一种投影类型)是工具生成的,而不是你自己创作的内容。
struct MyRuntimeClass : MyProject::IMyRuntimeClass, impl::require<MyRuntimeClass,Windows::Foundation::IStringable, Windows::Foundation::IClosable>
MyRuntimeClass 是投影类型;投影接口包括 IMyRuntimeClass 、IStringable 和 IClosable 。 本主题已展示你可用来实例化投影类型的不同方法。 以下是提醒和总结,这里使用 MyRuntimeClass 作为示例。
// The runtime class is implemented in another compilation unit (it's either a Windows API,
// or it's implemented in a second- or third-party component).
MyProject::MyRuntimeClass myrc1;// The runtime class is implemented in the same compilation unit.
MyProject::MyRuntimeClass myrc2{ nullptr };
myrc2 = winrt::make<MyProject::implementation::MyRuntimeClass>();
- 你可以访问一个投影类型的所有接口的成员。
- 可以将投影类型返回到调用方。
- 投影类型和接口派生自 winrt::Windows::Foundation::IUnknown 。 因此,你可以对投影类型或接口调用 IUnknown::as 以查询其他也可使用或返回到调用方的投影接口。 as 成员函数的工作方式类似于 QueryInterface 。
void f(MyProject::MyRuntimeClass const& myrc)
{myrc.ToString();myrc.Close();IClosable iclosable = myrc.as<IClosable>();iclosable.Close();
}
激活工厂
创建 C++/WinRT 对象的便利直接的方式如下所示。
using namespace winrt::Windows::Globalization::NumberFormatting;
...
CurrencyFormatter currency{ L"USD" };
不过,有时你可能想要自己创建激活工厂,然后在方便时从其创建对象。
下面的一些示例向你展示了如何使用 winrt::get_activation_factory 函数模板来实现此目的。
using namespace winrt::Windows::Globalization::NumberFormatting;
...
auto factory = winrt::get_activation_factory<CurrencyFormatter, ICurrencyFormatterFactory>();
CurrencyFormatter currency = factory.CreateCurrencyFormatterCode(L"USD");
using namespace winrt::Windows::Foundation;
...
auto factory = winrt::get_activation_factory<Uri, IUriRuntimeClassFactory>();
Uri uri = factory.CreateUri(L"http://www.contoso.com");
上面两个示例中的类是来自 Windows 命名空间的类型。 在接下来的示例中,ThermometerWRC::Thermometer 是在 Windows 运行时组件中实现的自定义类型。
auto factory = winrt::get_activation_factory<ThermometerWRC::Thermometer>();
ThermometerWRC::Thermometer thermometer = factory.ActivateInstance<ThermometerWRC::Thermometer>();
成员/类型多义性
当成员函数的名称与类型的名称相同时,会产生多义性。 根据 C++ 的在成员函数中进行非限定名称查找的规则,必须先搜索类,然后才能在命名空间中进行搜索。 “替换失败不是错误 (SFINAE)”规则不适用(在对函数模板进行重载解析时适用)。 因此,如果类中的名称没有意义,则编译器不会继续查找更好的匹配,它会直接报告一个错误。
struct MyPage : Page
{void DoWork(){// This doesn't compile. You get the error// "'winrt::Windows::Foundation::IUnknown::as':// no matching overloaded function found".auto style{ Application::Current().Resources().Lookup(L"MyStyle").as<Style>() };}
}
在上面的代码中,编译器认为你是在将 FrameworkElement.Style()(这在 C++/WinRT 中是成员函数)作为模板参数传递给 IUnknown::as。 解决方案是将名称 Style 强制解释为类型 Windows::UI::Xaml::Style。
struct MyPage : Page
{void DoWork(){// One option is to fully-qualify it.auto style{ Application::Current().Resources().Lookup(L"MyStyle").as<Windows::UI::Xaml::Style>() };// Another is to force it to be interpreted as a struct name.auto style{ Application::Current().Resources().Lookup(L"MyStyle").as<struct Style>() };// If you have "using namespace Windows::UI;", then this is sufficient.auto style{ Application::Current().Resources().Lookup(L"MyStyle").as<Xaml::Style>() };// Or you can force it to be resolved in the global namespace (into which// you imported the Windows::UI::Xaml namespace when you did// "using namespace Windows::UI::Xaml;".auto style = Application::Current().Resources().Lookup(L"MyStyle").as<::Style>();}
}
非限定名称查找有一个特殊的例外,即,名称后面跟有 ::,在这种情况下,它会忽略函数、变量和枚举值。 这样你就可以执行如下所示的代码。
struct MyPage : Page
{void DoSomething(){Visibility(Visibility::Collapsed); // No ambiguity here (special exception).}
}
对 Visibility() 的调用会解析为 UIElement.Visibility 成员函数名称。 但是参数 Visibility::Collapsed 在 Visibility 一词后面跟有 ::,因此系统会忽略方法名称,编译器会查找枚举类。
相关文章:
使用 C++/WinRT 创作 API
如果 API 位于 Windows 命名空间中 这是你使用 Windows 运行时 API 最常见的情况。 对于元数据中定义的 Windows 命名空间中的每个类型,C/WinRT 都定义了 C 友好等效项(称为投影类型 )。 投影类型具有与 Windows 类型相同的完全限定名称&…...
C#写windows服务,实现把检测软件崩溃工具写成服务 自动运行
一、打开Visual Studio,创建项目->Windows 服务(.NET Framework) 二、点击Service.cs 点击切换到代码视图 static Timer Timer; private Thread monitorThread; private static string logFilePath; private static Process winFormsProcess; public Service1(…...
QT中线程的退出分析
QT中线程的退出分析 前言开发环境代码的整改第一次修改第一次修改引起的问题问题原因分析解决方法第二次修改前言 软件实际开发过程中有好几处要实现这么一个功能:PC端软件“应用程序重启” ,本来这是一段比较简单的事情,但是因为重启软件报通信异常(错误日志中有记录通信…...
进程的创建
关于进程创建的一些细节都在注释中 /*#include <sys/types.h>#include <unistd.h>pid_t fork(void);函数的作用:用于创建子进程。返回值:fork()的返回值会返回两次。一次是在父进程中,一次是在子进程中。在父进程中返回创建的子…...
day-08 构造限制重复的字符串
思路 首先统计每个字符的个数,然后从后向前按照题意添加字符 解题方法 从后向前添加字符:1.当前字符个数<repeatLimit,直接添加 2.当前字符个数>repeatLimit,添加repeatLimit个,然后插入一个下一级字符 时间复杂度:O(n) 空间复杂度:…...
Java锁的分类
系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…...
SQL-分组查询
🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:重拾MySQL 🍹文章作者技术和水平很有限,如果文中出现错误&am…...
HBase 基础
HBase 基础 HBase1. HBase简介1.1 HBase定义1.2 HBase数据模型1.2.1 HBase逻辑结构1.2.2 HBase物理存储结构1.2.3 数据模型 1.3 HBase基本架构 2. HBase环境安装2.1 HBase 安装部署2.1.1 HBase 本地按照2.1.2 HBase 伪分布模式安装2.1.3 HBase 集群安装 2.2 HBase Shell操作2.2…...
android 11添加系统api供app使用
实现要求:添加系统api到sdk,公开给未签名app使用 1.将代码添加到 frameworks/base/core/java 目录下,创建自己的包名,这个路径下可以自动识别,更新到current.txt,不用改编译规则 比如:framework…...
im6ull学习总结(三-3)freetype
1、Freetype简介 FreeType是一个开源的字体渲染引擎,主要用于将字体文件转换为位图或矢量图形,并在屏幕上渲染出高质量的字体。它提供了一组API,使开发者能够在自己的应用程序中使用和呈现字体。 FreeType最初是作为一个独立项目开发的&…...
基于OpenCV的谷物颗粒识别
基于OpenCV的谷物颗粒识别 一、程序整体功能介绍1.1 导入库与函数定义1.2 颜色分割与灰度处理1.3 二值化与轮廓检测1.4 绘制与计数1.5 主程序与结果展示 二、算法原理与实现流程2.1算法原理(1)颜色分割(2)灰度处理与二值化&#x…...
Aloha 机械臂的学习记录3——AWE:Pycharm运行代码记录
之前的博客创作了三偏关于Aloha_AWE的liunx终端指令运行代码的示例: Aloha 机械臂的学习记录——AWE:Bimanual Simulation Suite: https://blog.csdn.net/qq_54900679/article/details/134889183?spm1001.2014.3001.5502 Aloha 机械臂的学习记录1——AWE&#x…...
开源协议概览
身为程序员,我们不可避免的要和开源项目打交道,不管是我们自己做了些开源项目,还是使用开源项目,对各种开源协议的了解是必要的。 OSI(Open Source Initiative) OSI,开发源代码组织,是一个旨在推动开源软件…...
分布式缓存
分布式缓存 缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间所有原本应该访问缓存的请求都去查询数据库了,而对数据库 CPU 和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应…...
BSC/平衡记分卡
一、Balanced Score Card BSC即平衡计分卡(Balanced Score Card),是常见的绩效考核方式之一,是从财务、客户、内部运营、学习与成长四个角度,将组织的战略落实为可操作的衡量指标和目标值的一种新型绩效管理体系。 是…...
论文阅读_训练大模型用于角色扮演
英文名称: Character-LLM: A Trainable Agent for Role-Playing 中文名称: 角色-LLM:训练Agent用于角色扮演 文章: [https://arxiv.org/abs/2310.10158](https://arxiv.org/abs/2310.10158) 作者: Yunfan Shao, Linyang Li, Junqi Dai, Xipeng Qiu 机构: 复旦大学…...
v-if控制div内容显示,克隆这个div但是v-if没有效果
问题描述: 我的子页面打印的时候通过isPdf来隐藏“选择参加人员”按钮。 我子页面有个el-dialog,el-dialog里面有个大的div它的id为app-pre-meet-add,在子页面我通过isPdf来显示我想要的内容。现在我在父页面先通过this.$refs.child.control…...
flutter的状态管理学习
文章目录 1.flutter widget分类2. 代理组件又分为3. 状态 state 数据4. 刷新 数据变化5. code 1.flutter widget分类 组合渲染代理 2. 代理组件又分为 Positioned向父组件传递数据InheritedWidget向子组件传递数据 3. 状态 state 数据 状态就是用到了向子组件传递数据ÿ…...
开源免费虚拟化KVM的部署及其虚拟机资源变更、快照、克隆等常见运维操作
实践说明:基于RHEL9(AlmaLinux9.1)部署,同类系统(CentOS9,RockyLinux9等)适用,但适用场景是不限于此的。 文档说明:本文档旨在帮助快速应用KVM虚拟化技术,重在实践操作,提供了简要参考。 文档形成时期&…...
阿里云git clone超时报错解决方法
参考:引用文章...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
