C++を使用してJNI DLLを作成し、JavaアプリケーションにWindows 10およびmacOS上のBluetooth LEデバイスにアクセスする方法を提供しています。 C++/CXを使用してWindows 10上のBluetooth LEオブジェクトにアクセスし、Objective-C++はmacOS上の同等物にアクセスします。しかし、この問題は、Windows 10で発生しているクラッシュに焦点を当てています。そのため、macOS固有のコードは分解されません。このクラッシュは、JNI経由または別のCエクスポートを介してDLLを使用しているときに発生しますデバッグを簡略化するために書いています)。Windows :: Devices :: Enumeration :: DeviceWatcher->スキャン時にStop()がクラッシュする
注:CentralManagerCppCxShim
はref class
で、イベントが発生するとCentralManagerImpl
にコールバックされます。 _deviceWatcher
が破壊取得したときにクラッシュする(Iはnullptr
に設定するか否かの違いはありません):
クラッシュスキャン(すなわちStartScan()
が呼び出された)を実行している間CentralManagerImpl
オブジェクトが破棄されるときに発生します。 BluetoothLEAdvertisementWatcher
と同様の問題がありましたが、デストラクタ内のイベントハンドラを適切に削除するとクラッシュが消えました。
コードの抜粋:
CentralManagerImpl.h:
class CentralManagerImpl: public CentralManager
{
private:
CentralManagerCppCxShim ^_shim;
DeviceWatcher ^_deviceWatcher;
BluetoothLEAdvertisementWatcher ^_watcher;
EventRegistrationToken _deviceWatcherAdded;
EventRegistrationToken _deviceWatcherRemoved;
EventRegistrationToken _deviceWatcherUpdated;
EventRegistrationToken _watcherReceived;
public:
CentralManagerImpl();
~CentralManagerImpl();
void StartScan();
void StopScan();
}
CentralManagerImpl.cpp:
CentralManagerImpl::CentralManagerImpl()
{
_shim = ref new CentralManagerCppCxShim(this);
_deviceWatcher = DeviceInformation::CreateWatcher(BluetoothLEDevice::GetDeviceSelectorFromPairingState(true));
_deviceWatcherAdded = _deviceWatcher->Added += ref new TypedEventHandler<DeviceWatcher ^, DeviceInformation ^>(_shim, &CentralManagerCppCxShim::OnDeviceAdded);
_deviceWatcherRemoved = _deviceWatcher->Removed += ref new TypedEventHandler<DeviceWatcher ^, DeviceInformationUpdate ^>(_shim, &CentralManagerCppCxShim::OnDeviceRemoved);
_deviceWatcherUpdated = _deviceWatcher->Updated += ref new TypedEventHandler<DeviceWatcher ^, DeviceInformationUpdate ^>(_shim, &CentralManagerCppCxShim::OnDeviceUpdated);
_deviceWatcher->Stopped += ref new TypedEventHandler<DeviceWatcher ^, Object ^>(_shim, &CentralManagerCppCxShim::OnDeviceWatcherStopped);
_watcher = ref new BluetoothLEAdvertisementWatcher();
BluetoothLEManufacturerData ^manufacturerData = ref new BluetoothLEManufacturerData();
manufacturerData->CompanyId = MAKEWORD(HIBYTE(OUR_COMPANY_IDENTIFIER), LOBYTE(OUR_COMPANY_IDENTIFIER));
_watcher->AdvertisementFilter->Advertisement->ManufacturerData->Append(manufacturerData);
_watcher->Stopped += ref new TypedEventHandler<BluetoothLEAdvertisementWatcher ^, BluetoothLEAdvertisementWatcherStoppedEventArgs ^>(_shim, &CentralManagerCppCxShim::OnAdvertisementWatcherStopped);
_watcherReceived = _watcher->Received += ref new TypedEventHandler<BluetoothLEAdvertisementWatcher ^, BluetoothLEAdvertisementReceivedEventArgs ^>(_shim, &CentralManagerCppCxShim::OnAdvertisementReceived);
}
CentralManagerImpl::~CentralManagerImpl()
{
_watcher->Received -= _watcherReceived;
_watcher = nullptr;
_deviceWatcher->Updated -= _deviceWatcherUpdated;
_deviceWatcher->Removed -= _deviceWatcherRemoved;
_deviceWatcher->Added -= _deviceWatcherAdded;
_deviceWatcher = nullptr; // this crashes :(
}
void CentralManagerImpl::StartScan()
{
_deviceWatcher->Start();
_watcher->Start();
}
void CentralManagerImpl::StopScan()
{
_watcher->Stop();
_deviceWatcher->Stop();
}
これは(はい、それは厄介だ)私は取得していますコールスタックです:
[email protected]()
[email protected]()
cfgmgr32.dll!TQuery::CloseQuery()
[email protected]()
Windows.Devices.Enumeration.dll!Watcher<class Windows::Devices::Enumeration::DeviceWatcher,struct Windows::Devices::Enumeration::IDeviceWatcher,struct Windows::Devices::Enumeration::IDeviceWatcher2,class Windows::Devices::Enumeration::DeviceInformation,struct Windows::Devices::Enumeration::IDeviceInformation,struct Windows::Devices::Enumeration::IDeviceInformation2,class DeviceInformationServer,class Windows::Devices::Enumeration::DeviceInformationUpdate,struct Windows::Devices::Enumeration::IDeviceInformationUpdate,class DeviceInformationUpdateServer,&unsigned short const * const RuntimeClass_Windows_Devices_Enumeration_DeviceWatcher>::Impl::EndQuery(void)
Windows.Devices.Enumeration.dll!Watcher<class Windows::Devices::Enumeration::DeviceWatcher,struct Windows::Devices::Enumeration::IDeviceWatcher,struct Windows::Devices::Enumeration::IDeviceWatcher2,class Windows::Devices::Enumeration::DeviceInformation,struct Windows::Devices::Enumeration::IDeviceInformation,struct Windows::Devices::Enumeration::IDeviceInformation2,class DeviceInformationServer,class Windows::Devices::Enumeration::DeviceInformationUpdate,struct Windows::Devices::Enumeration::IDeviceInformationUpdate,class DeviceInformationUpdateServer,&unsigned short const * const RuntimeClass_Windows_Devices_Enumeration_DeviceWatcher>::Impl::Stop(bool)
Windows.Devices.Enumeration.dll!Watcher<class Windows::Devices::Enumeration::DeviceWatcher,struct Windows::Devices::Enumeration::IDeviceWatcher,struct Windows::Devices::Enumeration::IDeviceWatcher2,class Windows::Devices::Enumeration::DeviceInformation,struct Windows::Devices::Enumeration::IDeviceInformation,struct Windows::Devices::Enumeration::IDeviceInformation2,class DeviceInformationServer,class Windows::Devices::Enumeration::DeviceInformationUpdate,struct Windows::Devices::Enumeration::IDeviceInformationUpdate,class DeviceInformationUpdateServer,&unsigned short const * const RuntimeClass_Windows_Devices_Enumeration_DeviceWatcher>::~Watcher<class Windows::Devices::Enumeration::DeviceWatcher,struct Windows::Devices::Enumeration::IDeviceWatcher,struct Windows::Devices::Enumeration::IDeviceWatcher2,class Windows::Devices::Enumeration::DeviceInformation,struct Windows::Devices::Enumeration::IDeviceInformation,struct Windows::Devices::Enumeration::IDeviceInformation2,class DeviceInformationServer,class Windows::Devices::Enumeration::Devic()
Windows.Devices.Enumeration.dll!Watcher<class Windows::Devices::Enumeration::DeviceWatcher,struct Windows::Devices::Enumeration::IDeviceWatcher,struct Windows::Devices::Enumeration::IDeviceWatcher2,class Windows::Devices::Enumeration::DeviceInformation,struct Windows::Devices::Enumeration::IDeviceInformation,struct Windows::Devices::Enumeration::IDeviceInformation2,class DeviceInformationServer,class Windows::Devices::Enumeration::DeviceInformationUpdate,struct Windows::Devices::Enumeration::IDeviceInformationUpdate,class DeviceInformationUpdateServer,&unsigned short const * const RuntimeClass_Windows_Devices_Enumeration_DeviceWatcher>::`vector deleting destructor'(unsigned int)
Windows.Devices.Enumeration.dll!Microsoft::WRL::Details::RuntimeClass<struct Microsoft::WRL::Details::InterfaceList<struct Windows::Devices::Enumeration::IDeviceWatcher,struct Microsoft::WRL::Details::InterfaceList<struct Windows::Devices::Enumeration::IDeviceWatcher2,struct Microsoft::WRL::Details::InterfaceList<struct Windows::Foundation::IClosable,struct Microsoft::WRL::Details::InterfaceList<class Microsoft::WRL::FtmBase,class Microsoft::WRL::Details::Nil> > > >,struct Microsoft::WRL::RuntimeClassFlags<3>,1,1,0>::Release(void)
mydll.dll!__abi_winrt_ptr_assign(void * * __ppTargetArg, const volatile Platform::Object^__objArg) Line 405
mydll.dll!CentralManagerImpl::~CentralManagerImpl() Line 64
[External Code]
//…
* "デストラクタのイベントハンドラを適切に削除するとクラッシュがなくなりました" * - あなたはすでに答えを知っているので、あなたの質問は何ですか? – IInspectable
同様の問題(BluetootheleAdvertisementWatcherで)がなくなりました。私はまだDeviceWatcherでクラッシュします。 – bbousquet
'_deviceWatcher-> Stopped'デリゲートを削除していないようです。 – IInspectable