diff --git a/doc/changelog.dox b/doc/changelog.dox index 571a57247..93434578b 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -155,6 +155,8 @@ See also: [mosra/magnum#312](https://github.com/mosra/magnum/pull/312)) @ref Trade::TgaImporter "TgaImporter" now properly reports an error message when opening an empty file +- @ref Trade::AbstractImporter::setFileCallback() now accepts callbacks with + @cpp const @ce references to user data as well @subsection changelog-latest-buildsystem Build system diff --git a/src/Magnum/Trade/AbstractImporter.h b/src/Magnum/Trade/AbstractImporter.h index f496306ba..5e6224edc 100644 --- a/src/Magnum/Trade/AbstractImporter.h +++ b/src/Magnum/Trade/AbstractImporter.h @@ -1239,7 +1239,7 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi /* Used by the templated version only */ struct FileCallbackTemplate { void(*callback)(); - void* userData; + const void* userData; } _fileCallbackTemplate{}; }; @@ -1250,10 +1250,10 @@ template void AbstractImporter::setFileCallback(Callbac const auto callbackPtr = static_cast>(*)(const std::string&, InputFileCallbackPolicy, T&)>(callback); if(!callbackPtr) return setFileCallback(nullptr); - _fileCallbackTemplate = { reinterpret_cast(callbackPtr), &userData }; + _fileCallbackTemplate = { reinterpret_cast(callbackPtr), static_cast(&userData) }; setFileCallback([](const std::string& filename, const InputFileCallbackPolicy flags, void* const userData) { auto& s = *reinterpret_cast(userData); - return reinterpret_cast>(*)(const std::string&, InputFileCallbackPolicy, T&)>(s.callback)(filename, flags, *static_cast(s.userData)); + return reinterpret_cast>(*)(const std::string&, InputFileCallbackPolicy, T&)>(s.callback)(filename, flags, *static_cast(const_cast(s.userData))); }, &_fileCallbackTemplate); } #endif diff --git a/src/Magnum/Trade/Test/AbstractImporterTest.cpp b/src/Magnum/Trade/Test/AbstractImporterTest.cpp index eb6909109..88ba5ca72 100644 --- a/src/Magnum/Trade/Test/AbstractImporterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImporterTest.cpp @@ -66,6 +66,7 @@ struct AbstractImporterTest: TestSuite::Tester { void setFileCallback(); void setFileCallbackTemplate(); void setFileCallbackTemplateNull(); + void setFileCallbackTemplateConst(); void setFileCallbackFileOpened(); void setFileCallbackNotImplemented(); void setFileCallbackNotSupported(); @@ -260,6 +261,7 @@ AbstractImporterTest::AbstractImporterTest() { &AbstractImporterTest::setFileCallback, &AbstractImporterTest::setFileCallbackTemplate, &AbstractImporterTest::setFileCallbackTemplateNull, + &AbstractImporterTest::setFileCallbackTemplateConst, &AbstractImporterTest::setFileCallbackFileOpened, &AbstractImporterTest::setFileCallbackNotImplemented, &AbstractImporterTest::setFileCallbackNotSupported, @@ -665,6 +667,29 @@ void AbstractImporterTest::setFileCallbackTemplateNull() { CORRADE_VERIFY(importer.called); } +void AbstractImporterTest::setFileCallbackTemplateConst() { + struct: AbstractImporter { + Features doFeatures() const override { return Feature::OpenData|Feature::FileCallback; } + bool doIsOpened() const override { return false; } + void doClose() override {} + void doSetFileCallback(Containers::Optional>(*)(const std::string&, InputFileCallbackPolicy, void*), void*) override { + called = true; + } + + bool called = false; + } importer; + + /* Just verify we can have const parameters */ + const int a = 0; + auto lambda = [](const std::string&, InputFileCallbackPolicy, const int&) { + return Containers::Optional>{}; + }; + importer.setFileCallback(lambda, a); + CORRADE_VERIFY(importer.fileCallback()); + CORRADE_VERIFY(importer.fileCallbackUserData()); + CORRADE_VERIFY(importer.called); +} + void AbstractImporterTest::setFileCallbackFileOpened() { struct: AbstractImporter { Features doFeatures() const override { return {}; }