diff --git a/src/bb/image-io/rt_u3v.h b/src/bb/image-io/rt_u3v.h index 67266716..2e6fb572 100644 --- a/src/bb/image-io/rt_u3v.h +++ b/src/bb/image-io/rt_u3v.h @@ -328,7 +328,7 @@ class U3V { protected: U3V(int32_t num_sensor, bool frame_sync, bool realtime_display_mode, bool sim_mode, int32_t width, int32_t height , float_t fps, const std::string & pixel_format, char* dev_id = nullptr) - : gobject_(GOBJECT_FILE, true), aravis_(ARAVIS_FILE, true), + : gobject_(GOBJECT_FILE, true), aravis_(ARAVIS_FILE, true, true), num_sensor_(num_sensor), frame_count_method_(FrameCountMethod::UNAVAILABLE), frame_sync_(frame_sync), realtime_display_mode_(realtime_display_mode), is_gendc_(false), is_param_integer_(false), devices_(num_sensor), buffers_(num_sensor), operation_mode_(OperationMode::Came1USB1), frame_cnt_(0), device_idx_(-1), disposed_(false), sim_mode_(sim_mode), order_filp_(false) @@ -357,9 +357,6 @@ class U3V { } void init_symbols_aravis() { - if (!aravis_.is_available()) { - throw ::std::runtime_error("libaravis-0.8 is unavailable on your system."); - } #define GET_SYMBOL(LOCAL_VAR, TARGET_SYMBOL) \ LOCAL_VAR = aravis_.get_symbol(TARGET_SYMBOL); \ diff --git a/src/dynamic_module.h b/src/dynamic_module.h index 92092bc9..ed0bdd83 100644 --- a/src/dynamic_module.h +++ b/src/dynamic_module.h @@ -6,6 +6,7 @@ #if _WIN32 #define WIN32_LEAN_AND_MEAN #include +#include #define ION_DYNAMIC_MODULE_PREFIX "" #define ION_DYNAMIC_MODULE_EXT ".dll" #elif __APPLE__ @@ -29,100 +30,155 @@ bool has_prefix_and_ext(const std::string& n) { namespace ion { class DynamicModule { - public: +public: +#ifdef _WIN32 + using Handle = HMODULE; +#else + using Handle = void *; +#endif + DynamicModule(const std::string& module_name_or_path, bool essential = true, bool lazy_load = false) { + if (module_name_or_path == "") { + handle_ = nullptr; + return; + } + + // set target + std::string target; + if (std::filesystem::exists(module_name_or_path) || has_prefix_and_ext(module_name_or_path)) { + // This is absolute path or file name + target = module_name_or_path; + } else { + target = std::string(ION_DYNAMIC_MODULE_PREFIX) + module_name_or_path + std::string(ION_DYNAMIC_MODULE_EXT); + } + target_ = target; + essential_ = essential; + + if (lazy_load) { #ifdef _WIN32 - using Handle = HMODULE; + handle_ = nullptr; #else - using Handle = void*; + handle_ = RTLD_DEFAULT; #endif + } else { - DynamicModule(const std::string& module_name_or_path, bool essential = true) { - if (module_name_or_path == "") { - handle_ = nullptr; - return; - } - - std::string target; - if (std::filesystem::exists(module_name_or_path) || has_prefix_and_ext(module_name_or_path)) { - // This is absolute path or file name - target = module_name_or_path; - } else { - target = std::string(ION_DYNAMIC_MODULE_PREFIX) + module_name_or_path + std::string(ION_DYNAMIC_MODULE_EXT); - } - - // TODO: WIP: test moduel_name_or_path using std::filesystem + // TODO: WIP: test moduel_name_or_path using std::filesystem #ifdef _WIN32 - handle_ = LoadLibraryA(target.c_str()); + handle_ = LoadLibraryA(target.c_str()); #else - handle_ = dlopen(target.c_str(), RTLD_NOW); + handle_ = dlopen(target.c_str(), RTLD_NOW); #endif - if (handle_ == nullptr) { - if (essential) { - throw std::runtime_error(getErrorString()); - } else { - log::warn("Not found inessential library {} : {}", target, getErrorString()); - } - } - } - - ~DynamicModule() { - if (handle_ != nullptr) { - // NOTE: DSO which is loaded by with_bb_module should not be unloaded even if Builder is destructed. - // Loading more than twice does not have any side effects. - } - } + if (handle_ == nullptr) { + if (essential) { + throw std::runtime_error(getErrorString()); + } else { + log::warn("Not found inessential library {} : {}", target, getErrorString()); + } + } + } + } + + ~DynamicModule() { + if (handle_ != nullptr) { + // NOTE: DSO which is loaded by with_bb_module should not be unloaded even if Builder is destructed. + // Loading more than twice does not have any side effects. + } + } bool is_available(void) const { - return handle_ != NULL; + return handle_ != nullptr; } template - T get_symbol(const std::string &symbol_name) const { -#if defined(_WIN32) - return reinterpret_cast(GetProcAddress(handle_, symbol_name.c_str())); + T get_symbol(const std::string &symbol_name) { +#ifdef _WIN32 + if (handle_ != nullptr) { + return reinterpret_cast(GetProcAddress(handle_, symbol_name.c_str())); + } else { + // search symbol globally first + Handle hmods[1024]; // the array size should be large enough + DWORD cb_needed; + if (EnumProcessModules(GetCurrentProcess(), hmods, sizeof(hmods), &cb_needed)) { + for (unsigned int i = 0; i < (cb_needed / sizeof(HMODULE)); i++) { + char path[MAX_PATH]; + // Get the module name + if (GetModuleFileNameA(hmods[i], path, sizeof(path) / sizeof(char))) { + // Try to get the address of the symbol if module path includes target_ + std::string module_path(path); + if (module_path.find(target_) != std::string::npos) { + handle_ = hmods[i]; + return reinterpret_cast(GetProcAddress(hmods[i], symbol_name.c_str())); + } + } + } + } + // failed to load symbol gloablly, load it explicitly + handle_ = LoadLibraryA(target_.c_str()); + if (handle_ != nullptr) { + log::info("Lazy loading library {}", target_); + } else { + if (essential_) { + throw std::runtime_error(getErrorString()); + } + } + return reinterpret_cast(GetProcAddress(handle_, symbol_name.c_str())); + } #else - return reinterpret_cast(dlsym(handle_, symbol_name.c_str())); + if (handle_ == RTLD_DEFAULT) { + void *func_ptr = dlsym(handle_, symbol_name.c_str()); + if (func_ptr != nullptr) { + return reinterpret_cast(func_ptr); + } else { + handle_ = dlopen(target_.c_str(), RTLD_NOW); + if (handle_ != nullptr) { + log::info("Lazy loading library {}", target_); + } else { + if (essential_) { + throw std::runtime_error(getErrorString()); + } + } + return reinterpret_cast(dlsym(handle_, symbol_name.c_str())); + } + } else { + return reinterpret_cast(dlsym(handle_, symbol_name.c_str())); + } #endif } - - private: - - std::string getErrorString(void) const { - std::string error_msg; +private: + std::string getErrorString(void) const { + std::string error_msg; #ifdef _WIN32 - DWORD error = GetLastError(); - if (error) - { - LPVOID lpMsgBuf; - DWORD bufLen = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, - error, - MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), - (LPTSTR) &lpMsgBuf, 0, nullptr ); - if (bufLen) - { - LPCSTR lpMsgStr = (LPCSTR)lpMsgBuf; - error_msg = std::string(lpMsgStr, lpMsgStr+bufLen); - LocalFree(lpMsgBuf); - } - } + DWORD error = GetLastError(); + if (error) { + LPVOID lpMsgBuf; + DWORD bufLen = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + error, + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + (LPTSTR)&lpMsgBuf, 0, nullptr); + if (bufLen) { + LPCSTR lpMsgStr = (LPCSTR)lpMsgBuf; + error_msg = std::string(lpMsgStr, lpMsgStr + bufLen); + LocalFree(lpMsgBuf); + } + } #else - const char* buf(dlerror()); - error_msg.assign(buf ? buf : "none"); + const char *buf(dlerror()); + error_msg.assign(buf ? buf : "none"); #endif - return error_msg; - } - + return error_msg; + } - Handle handle_; + Handle handle_; + std::string target_; + bool essential_; }; -} // namespace ion +} // namespace ion -#endif // ION_DYNAMIC_MODULE_H +#endif // ION_DYNAMIC_MODULE_H