2017-01-23 8 views
0

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()がクラッシュする

注:CentralManagerCppCxShimref 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] 
//… 
+0

* "デストラクタのイベントハンドラを適切に削除するとクラッシュがなくなりました" * - あなたはすでに答えを知っているので、あなたの質問は何ですか? – IInspectable

+0

同様の問題(BluetootheleAdvertisementWatcherで)がなくなりました。私はまだDeviceWatcherでクラッシュします。 – bbousquet

+0

'_deviceWatcher-> Stopped'デリゲートを削除していないようです。 – IInspectable

答えて

0

A DLLがすでにによって終了されているUWPワーカースレッドとして(DLL_PROCESS_DETACH)をアンロードされたときに、システムがCentralManagerImpl C++クラスの既定のデストラクタでDeviceWatcherを破壊することはできません

:FTERより深い調査は、私は次のような結論になってきましたシステム。私が見つけた唯一の解決策は、明示的に私のC + +クラスを引き裂くために私のDLLに新しいエクスポートを追加することでした。

私はこれを別の方法があるとは思わないので、これを回答としてマークします。

関連する問題