diff --git a/Core/Code/CppMicroServices/src/module/usModuleUtils.cpp b/Core/Code/CppMicroServices/src/module/usModuleUtils.cpp index 4cea854204..cc5ff30c76 100644 --- a/Core/Code/CppMicroServices/src/module/usModuleUtils.cpp +++ b/Core/Code/CppMicroServices/src/module/usModuleUtils.cpp @@ -1,155 +1,166 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include "usModuleUtils_p.h" #include US_BEGIN_NAMESPACE #ifdef __GNUC__ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include std::string GetLibraryPath_impl(const std::string& /*libName*/, void* symbol) { Dl_info info; if (dladdr(symbol, &info)) { return info.dli_fname; } else { - US_DEBUG << GetLastErrorStr(); + US_DEBUG << "GetLibraryPath_impl() dladdr() failed: " << dlerror(); } return ""; } void* GetSymbol_impl(const std::string& libName, const char* symbol) { + // Clear the last error message + dlerror(); + void* selfHandle = 0; if (libName.empty()) { // Get the handle of the executable selfHandle = dlopen(0, RTLD_LAZY); } else { selfHandle = dlopen(libName.c_str(), RTLD_LAZY); } if (selfHandle) { void* addr = dlsym(selfHandle, symbol); + if (!addr) + { + const char* dlerrorMsg = dlerror(); + if (dlerrorMsg) + { + US_DEBUG << "GetSymbol_impl() failed: " << dlerrorMsg; + } + } dlclose(selfHandle); return addr; } else { - US_DEBUG << GetLastErrorStr(); + US_DEBUG << "GetSymbol_impl() dlopen() failed: " << dlerror(); } return 0; } #elif _WIN32 #include std::string GetLibraryPath_impl(const std::string& libName, void *symbol) { HMODULE handle = 0; if (libName.empty()) { // get the handle for the executable handle = GetModuleHandle(0); } else { handle = GetModuleHandle(libName.c_str()); } if (!handle) { US_DEBUG << "GetLibraryPath_impl():GetModuleHandle() " << GetLastErrorStr(); return ""; } char modulePath[512]; if (GetModuleFileName(handle, modulePath, 512)) { return modulePath; } US_DEBUG << "GetLibraryPath_impl():GetModuleFileName() " << GetLastErrorStr(); return ""; } void* GetSymbol_impl(const std::string& libName, const char* symbol) { HMODULE handle = NULL; if (libName.empty()) { handle = GetModuleHandle(NULL); } else { handle = GetModuleHandle(libName.c_str()); } if (!handle) { US_DEBUG << "GetSymbol_impl():GetModuleHandle() " << GetLastErrorStr(); return 0; } void* addr = (void*)GetProcAddress(handle, symbol); if (!addr) { US_DEBUG << "GetSymbol_impl():GetProcAddress(handle," << symbol << ") " << GetLastErrorStr(); } return addr; } #else std::string GetLibraryPath_impl(const std::string& libName, void* symbol) { return ""; } void* GetSymbol_impl(const std::string& libName, const char* symbol) { return 0; } #endif std::string ModuleUtils::GetLibraryPath(const std::string& libName, void* symbol) { return GetLibraryPath_impl(libName, symbol); } void* ModuleUtils::GetSymbol(const std::string& libName, const char* symbol) { return GetSymbol_impl(libName, symbol); } US_END_NAMESPACE diff --git a/Core/Code/CppMicroServices/src/util/usUtils_p.h b/Core/Code/CppMicroServices/src/util/usUtils_p.h index 1e5b5d2065..25a4a2d0e4 100644 --- a/Core/Code/CppMicroServices/src/util/usUtils_p.h +++ b/Core/Code/CppMicroServices/src/util/usUtils_p.h @@ -1,207 +1,210 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #ifndef USUTILS_H #define USUTILS_H #include #include #include #include //------------------------------------------------------------------- // Logging //------------------------------------------------------------------- US_BEGIN_NAMESPACE US_EXPORT void message_output(MsgType, const char* buf); struct LogMsg { - LogMsg(int t) : type(static_cast(t)), enabled(true), buffer() {} + LogMsg(int t, const char* file, int ln, const char* func) + : type(static_cast(t)), enabled(true), buffer() + { buffer << "In " << func << " at " << file << ":" << ln << " : "; } + ~LogMsg() { if(enabled) message_output(type, buffer.str().c_str()); } template LogMsg& operator<<(T t) { if (enabled) buffer << t; return *this; } LogMsg& operator()(bool flag) { this->enabled = flag; return *this; } private: MsgType type; bool enabled; std::stringstream buffer; }; struct NoLogMsg { template NoLogMsg& operator<<(T) { return *this; } NoLogMsg& operator()(bool) { return *this; } }; US_END_NAMESPACE #if !defined(US_NO_DEBUG_OUTPUT) - #define US_DEBUG US_PREPEND_NAMESPACE(LogMsg)(0) + #define US_DEBUG US_PREPEND_NAMESPACE(LogMsg)(0, __FILE__, __LINE__, __FUNCTION__) #else - #define US_DEBUG US_PREPEND_NAMESPACE(NoLogMsg)() + #define US_DEBUG true ? US_PREPEND_NAMESPACE(NoLogMsg)() : US_PREPEND_NAMESPACE(NoLogMsg)() #endif #if !defined(US_NO_INFO_OUTPUT) - #define US_INFO US_PREPEND_NAMESPACE(LogMsg)(1) + #define US_INFO US_PREPEND_NAMESPACE(LogMsg)(1, __FILE__, __LINE__, __FUNCTION__) #else - #define US_INFO US_PREPEND_NAMESPACE(NoLogMsg)() + #define US_INFO true ? US_PREPEND_NAMESPACE(NoLogMsg)() : US_PREPEND_NAMESPACE(NoLogMsg)() #endif #if !defined(US_NO_WARNING_OUTPUT) - #define US_WARN US_PREPEND_NAMESPACE(LogMsg)(2) + #define US_WARN US_PREPEND_NAMESPACE(LogMsg)(2, __FILE__, __LINE__, __FUNCTION__) #else - #define US_WARN US_PREPEND_NAMESPACE(LogMsg)() + #define US_WARN true ? US_PREPEND_NAMESPACE(LogMsg)() : US_PREPEND_NAMESPACE(LogMsg)() #endif -#define US_ERROR US_PREPEND_NAMESPACE(LogMsg)(3) +#define US_ERROR US_PREPEND_NAMESPACE(LogMsg)(3, __FILE__, __LINE__, __FUNCTION__) //------------------------------------------------------------------- // Error handling //------------------------------------------------------------------- US_BEGIN_NAMESPACE US_EXPORT std::string GetLastErrorStr(); US_END_NAMESPACE //------------------------------------------------------------------- // Functors //------------------------------------------------------------------- #include #include #if defined(US_USE_CXX11) || defined(__GNUC__) #ifdef US_USE_CXX11 #include #define US_MODULE_LISTENER_FUNCTOR std::function #define US_SERVICE_LISTENER_FUNCTOR std::function #else #include #define US_MODULE_LISTENER_FUNCTOR std::tr1::function #define US_SERVICE_LISTENER_FUNCTOR std::tr1::function #endif US_BEGIN_NAMESPACE template US_MODULE_LISTENER_FUNCTOR ModuleListenerMemberFunctor(X* x, void (X::*memFn)(const US_PREPEND_NAMESPACE(ModuleEvent))) { return std::bind1st(std::mem_fun(memFn), x); } US_END_NAMESPACE US_BEGIN_NAMESPACE struct ModuleListenerCompare : std::binary_function { bool operator()(const US_MODULE_LISTENER_FUNCTOR& f1, const US_MODULE_LISTENER_FUNCTOR& f2) const { return f1.target() == f2.target(); } }; US_END_NAMESPACE US_BEGIN_NAMESPACE template US_SERVICE_LISTENER_FUNCTOR ServiceListenerMemberFunctor(X* x, void (X::*memFn)(const US_PREPEND_NAMESPACE(ServiceEvent))) { return std::bind1st(std::mem_fun(memFn), x); } US_END_NAMESPACE US_BEGIN_NAMESPACE struct ServiceListenerCompare : std::binary_function { bool operator()(const US_SERVICE_LISTENER_FUNCTOR& f1, const US_SERVICE_LISTENER_FUNCTOR& f2) const { return f1.target() == f2.target(); } }; US_END_NAMESPACE #else #include #define US_MODULE_LISTENER_FUNCTOR US_PREPEND_NAMESPACE(Functor) US_BEGIN_NAMESPACE template US_MODULE_LISTENER_FUNCTOR ModuleListenerMemberFunctor(X* x, MemFn memFn) { return Functor(x, memFn); } US_END_NAMESPACE US_BEGIN_NAMESPACE struct ModuleListenerCompare : std::binary_function { bool operator()(const US_MODULE_LISTENER_FUNCTOR& f1, const US_MODULE_LISTENER_FUNCTOR& f2) const { return f1 == f2; } }; US_END_NAMESPACE #define US_SERVICE_LISTENER_FUNCTOR US_PREPEND_NAMESPACE(Functor) US_BEGIN_NAMESPACE template US_SERVICE_LISTENER_FUNCTOR ServiceListenerMemberFunctor(X* x, MemFn memFn) { return Functor(x, memFn); } US_END_NAMESPACE US_BEGIN_NAMESPACE struct ServiceListenerCompare : std::binary_function { bool operator()(const US_SERVICE_LISTENER_FUNCTOR& f1, const US_SERVICE_LISTENER_FUNCTOR& f2) const { return f1 == f2; } }; US_END_NAMESPACE #endif #endif // USUTILS_H diff --git a/Core/Code/CppMicroServices/test/usDebugOutputTest.cpp b/Core/Code/CppMicroServices/test/usDebugOutputTest.cpp index c93de8c554..721ad6e351 100644 --- a/Core/Code/CppMicroServices/test/usDebugOutputTest.cpp +++ b/Core/Code/CppMicroServices/test/usDebugOutputTest.cpp @@ -1,100 +1,100 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include #include "usTestingMacros.h" US_USE_NAMESPACE static int lastMsgType = -1; static std::string lastMsg; void handleMessages(MsgType type, const char* msg) { lastMsgType = type; lastMsg.assign(msg); } void resetLastMsg() { lastMsgType = -1; lastMsg.clear(); } int usDebugOutputTest(int /*argc*/, char* /*argv*/[]) { US_TEST_BEGIN("DebugOutputTest"); // Use the default message handler { US_DEBUG << "Msg"; US_DEBUG(false) << "Msg"; US_INFO << "Msg"; US_INFO(false) << "Msg"; US_WARN << "Msg"; US_WARN(false) << "Msg"; } US_TEST_CONDITION(lastMsg.empty(), "Testing default message handler"); resetLastMsg(); installMsgHandler(handleMessages); { US_DEBUG << "Msg"; } #ifdef NDEBUG US_TEST_CONDITION(lastMsgType == -1 && lastMsg.empty(), "Testing suppressed debug message") #else - US_TEST_CONDITION(lastMsgType == 0 && lastMsg == "Msg", "Testing debug message") + US_TEST_CONDITION(lastMsgType == 0 && lastMsg.find("Msg") != std::string::npos, "Testing debug message") #endif resetLastMsg(); { US_DEBUG(false) << "No msg"; } US_TEST_CONDITION(lastMsgType == -1 && lastMsg.empty(), "Testing disabled debug message") resetLastMsg(); { US_INFO << "Info msg"; } - US_TEST_CONDITION(lastMsgType == 1 && lastMsg == "Info msg", "Testing informational message") + US_TEST_CONDITION(lastMsgType == 1 && lastMsg.find("Info msg") != std::string::npos, "Testing informational message") resetLastMsg(); { US_WARN << "Warn msg"; } - US_TEST_CONDITION(lastMsgType == 2 && lastMsg == "Warn msg", "Testing warning message") + US_TEST_CONDITION(lastMsgType == 2 && lastMsg.find("Warn msg") != std::string::npos, "Testing warning message") resetLastMsg(); // We cannot test US_ERROR since it will call abort(). installMsgHandler(0); { US_INFO << "Info msg"; } US_TEST_CONDITION(lastMsgType == -1 && lastMsg.empty(), "Testing message handler reset") US_TEST_END() }