如何在无UWP UI的C++ DLL中调用C++/WinRT的LampArray API?
在无UWP UI依赖的C++ DLL中使用LampArray DeviceWatcher
完全可以在独立的C++ DLL中调用LampArray相关API,无需依赖UWP UI组件。原示例的耦合点在于使用了UI页面类的弱引用(get_weak())和类成员回调,只需将这部分逻辑替换为独立的事件处理机制即可。
核心解决方案步骤
- 移除UI类依赖:创建DLL专属的设备管理类,替代原UI页面类的角色,用于管理DeviceWatcher和设备列表。
- 使用Lambda或独立回调函数:通过Lambda捕获管理类的弱引用(避免悬垂指针),或者使用普通函数结合上下文指针来处理设备添加/移除事件。
- 正确管理事件Revoker生命周期:将
event_token_revoker保存为管理类的成员,确保在类销毁时自动注销事件,避免资源泄漏。
示例实现代码
#include <winrt/Windows.Devices.Lights.h> #include <winrt/Windows.Foundation.h> #include <vector> #include <algorithm> namespace winrt::LampArrayDll::implementation { class LampDeviceManager { public: LampDeviceManager() { // 创建设备监视器 m_deviceWatcher = winrt::Windows::Devices::Lights::LampArray::CreateWatcher(); // 注册设备添加事件:用弱引用捕获当前实例,避免生命周期问题 m_deviceAddedRevoker = m_deviceWatcher.Added(winrt::auto_revoke, [weakThis = get_weak()](auto const&, winrt::Windows::Devices::Lights::LampArray const& lampArray) { if (auto strongThis = weakThis.lock()) { strongThis->OnDeviceAdded(lampArray); } }); // 注册设备移除事件 m_deviceRemovedRevoker = m_deviceWatcher.Removed(winrt::auto_revoke, [weakThis = get_weak()](auto const&, winrt::Windows::Devices::Lights::LampArrayRemovedEventArgs const& args) { if (auto strongThis = weakThis.lock()) { strongThis->OnDeviceRemoved(args.DeviceId()); } }); // 启动监视器 m_deviceWatcher.Start(); } ~LampDeviceManager() { // 停止监视器,避免后台线程持续运行 if (m_deviceWatcher.Status() == winrt::Windows::Devices::Enumeration::DeviceWatcherStatus::Started) { m_deviceWatcher.Stop(); } } // 对外暴露的接口:获取当前连接的所有灯设备 std::vector<winrt::Windows::Devices::Lights::LampArray> GetConnectedLamps() { std::vector<winrt::Windows::Devices::Lights::LampArray> lamps; // 同步枚举所有设备 auto deviceCollection = winrt::Windows::Devices::Lights::LampArray::FindAllAsync().get(); for (auto const& lamp : deviceCollection) { lamps.push_back(lamp); } return lamps; } private: // 设备添加处理逻辑 void OnDeviceAdded(winrt::Windows::Devices::Lights::LampArray const& lampArray) { m_connectedLamps.push_back(lampArray); // 这里可以添加自定义逻辑,比如通知上层设备已添加 } // 设备移除处理逻辑 void OnDeviceRemoved(hstring const& deviceId) { auto it = std::remove_if(m_connectedLamps.begin(), m_connectedLamps.end(), [&deviceId](const auto& lamp) { return lamp.DeviceId() == deviceId; }); m_connectedLamps.erase(it, m_connectedLamps.end()); // 这里可以添加自定义逻辑,比如通知上层设备已移除 } winrt::Windows::Devices::Lights::LampArrayWatcher m_deviceWatcher; winrt::event_token_revoker<winrt::Windows::Devices::Lights::LampArrayAddedEventHandler> m_deviceAddedRevoker; winrt::event_token_revoker<winrt::Windows::Devices::Lights::LampArrayRemovedEventHandler> m_deviceRemovedRevoker; std::vector<winrt::Windows::Devices::Lights::LampArray> m_connectedLamps; }; } // 对外暴露的DLL接口示例 extern "C" __declspec(dllexport) void* CreateLampManager() { return new winrt::LampArrayDll::implementation::LampDeviceManager(); } extern "C" __declspec(dllexport) void DestroyLampManager(void* manager) { delete static_cast<winrt::LampArrayDll::implementation::LampDeviceManager*>(manager); }
关键注意事项
- 编译配置:确保DLL项目启用C++/WinRT支持,并链接Windows SDK中的
windows.devices.lights.lib库。 - 线程安全:DeviceWatcher的事件会在后台线程触发,若回调逻辑涉及共享资源访问,需添加线程同步(如临界区、mutex)。
- 权限配置:若DLL被桌面应用调用,需在应用清单中声明设备权限:
<Capabilities> <DeviceCapability Name="lowLevel" /> </Capabilities> - 生命周期管理:在DLL对外接口中,需提供明确的创建/销毁方法,确保LampDeviceManager实例被正确释放,避免资源泄漏。
内容的提问来源于stack exchange,提问作者sunil
相关产品推荐
相关产品推荐

