📄 ncbidll.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbidll.cpp,v $ * PRODUCTION Revision 1000.5 2004/06/01 19:09:00 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20 * PRODUCTION * =========================================================================== *//* $Id: ncbidll.cpp,v 1000.5 2004/06/01 19:09:00 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Vladimir Ivanov, Denis Vakatov * * File Description: * Portable DLL handling * */#include <ncbi_pch.hpp>#include <corelib/ncbidll.hpp>#include <corelib/ncbifile.hpp>#if defined(NCBI_OS_MSWIN)# include <corelib/ncbi_os_mswin.hpp>#elif defined(NCBI_OS_UNIX)# ifdef HAVE_DLFCN_H# include <dlfcn.h># endif#else# error "Class CDll defined only for MS Windows and UNIX platforms"#endifBEGIN_NCBI_SCOPE// Platform-dependent DLL handle type definitionstruct SDllHandle {#if defined(NCBI_OS_MSWIN) HMODULE handle;#elif defined(NCBI_OS_UNIX) void* handle;#endif};CDll::CDll(const string& name, ELoad when_to_load, EAutoUnload auto_unload, EBasename treate_as){ x_Init(kEmptyStr, name, when_to_load, auto_unload, treate_as);}CDll::CDll(const string& path, const string& name, ELoad when_to_load, EAutoUnload auto_unload, EBasename treate_as){ x_Init(path, name, when_to_load, auto_unload, treate_as);}CDll::~CDll() { // Unload DLL automaticaly if ( m_AutoUnload ) { try { Unload(); } catch(CException& e) { NCBI_REPORT_EXCEPTION("CDll destructor", e); } } delete m_Handle;}void CDll::x_Init(const string& path, const string& name, ELoad when_to_load, EAutoUnload auto_unload, EBasename treate_as){ // Init members m_Handle = 0; m_AutoUnload = auto_unload == eAutoUnload; string x_name = name;#if defined(NCBI_OS_MSWIN) NStr::ToLower(x_name);#endif // Process DLL name if (treate_as == eBasename && name.find_first_of(":/\\") == NPOS &&#if defined(NCBI_OS_MSWIN) !CDirEntry::MatchesMask(name.c_str(),"*.dll")#elif defined(NCBI_OS_UNIX) !CDirEntry::MatchesMask(name.c_str(),"lib*.so") && !CDirEntry::MatchesMask(name.c_str(),"lib*.so.*")#endif ) { // "name" is basename#if defined(NCBI_OS_MSWIN) x_name = x_name + ".dll";#elif defined(NCBI_OS_UNIX) x_name = "lib" + x_name + ".so";#endif } m_Name = CDirEntry::ConcatPath(path, x_name); // Load DLL now if indicated if (when_to_load == eLoadNow) { Load(); }}void CDll::Load(void){ // DLL is already loaded if ( m_Handle ) { return; } // Load DLL#if defined(NCBI_OS_MSWIN) HMODULE handle = LoadLibrary(m_Name.c_str());#elif defined(NCBI_OS_UNIX)# ifdef HAVE_DLFCN_H void* handle = dlopen(m_Name.c_str(), RTLD_LAZY | RTLD_GLOBAL);# else void* handle = 0;# endif#endif if ( !handle ) { x_ThrowException("CDll::Load"); } m_Handle = new SDllHandle; m_Handle->handle = handle;}void CDll::Unload(void){ // DLL is not loaded if ( !m_Handle ) { return; } // Unload DLL#if defined(NCBI_OS_MSWIN) BOOL unloaded = FreeLibrary(m_Handle->handle);#elif defined(NCBI_OS_UNIX)# ifdef HAVE_DLFCN_H bool unloaded = dlclose(m_Handle->handle) == 0;# else bool unloaded = false;# endif#endif if ( !unloaded ) { x_ThrowException("CDll::Unload"); } delete m_Handle; m_Handle = 0;}CDll::TEntryPoint CDll::GetEntryPoint(const string& name){ // If DLL is not yet loaded if ( !m_Handle ) { Load(); } // Add leading underscore on Darwin platform#if defined(NCBI_OS_DARWIN) const string entry_name = "_" + name;#else const string entry_name = name;#endif TEntryPoint entry; // Return address of entry (function or data)#if defined(NCBI_OS_MSWIN) FARPROC ptr = GetProcAddress(m_Handle->handle, entry_name.c_str());#elif defined(NCBI_OS_UNIX) void* ptr = 0;# if defined(HAVE_DLFCN_H) ptr = dlsym(m_Handle->handle, entry_name.c_str());# if defined(NCBI_OS_DARWIN) // Try again without the underscore, since 10.3 and up don't need it. if ( !ptr ) { ptr = dlsym(m_Handle->handle, entry_name.c_str() + 1); }# endif# endif#else void* ptr = 0;#endif entry.func = (FEntryPoint)ptr; entry.data = ptr; return entry;}void CDll::x_ThrowException(const string& what){#if defined(NCBI_OS_MSWIN) char* ptr = NULL; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &ptr, 0, NULL); string errmsg = ptr ? ptr : "unknown reason"; LocalFree(ptr);#elif defined(NCBI_OS_UNIX)# ifdef HAVE_DLFCN_H const char* errmsg = dlerror(); if ( !errmsg ) { errmsg = "unknown reason"; }# else const char* errmsg = "No DLL support on this platform.";# endif#endif NCBI_THROW(CCoreException, eDll, what + " [" + m_Name +"]: " + errmsg);}CDllResolver::CDllResolver(const string& entry_point_name){ m_EntryPoinNames.push_back(entry_point_name);}CDllResolver::CDllResolver(const vector<string>& entry_point_names){ m_EntryPoinNames = entry_point_names;}CDllResolver::~CDllResolver(){ Unload();}bool CDllResolver::TryCandidate(const string& file_name){ try { CDll* dll = new CDll(file_name, CDll::eLoadNow, CDll::eAutoUnload); CDll::TEntryPoint p; SResolvedEntry entry_point(dll); ITERATE(vector<string>, it, m_EntryPoinNames) { string entry_point_name; const string& dll_name = dll->GetName(); if (!dll_name.empty()) { string base_name; CDirEntry::SplitPath(entry_point_name, 0, &base_name, 0); NStr::Replace(*it, "${basename}", base_name, entry_point_name); } // Check for the BASE library name macro if (entry_point_name.empty()) continue; p = dll->GetEntryPoint(entry_point_name); if (p.data) { entry_point.entry_points.push_back(SNamedEntryPoint(entry_point_name, p)); } } // ITERATE if (entry_point.entry_points.empty()) { delete dll; return false; } m_ResolvedEntries.push_back(entry_point); } catch (CCoreException& ex) { if (ex.GetErrCode() != CCoreException::eDll) throw; return false; } return true;}void CDllResolver::Unload(){ NON_CONST_ITERATE(TEntries, it, m_ResolvedEntries) { delete it->dll; } m_ResolvedEntries.resize(0); }END_NCBI_SCOPE/* * =========================================================================== * $Log: ncbidll.cpp,v $ * Revision 1000.5 2004/06/01 19:09:00 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20 * * Revision 1.20 2004/05/14 13:59:27 gorelenk * Added include of ncbi_pch.hpp * * Revision 1.19 2004/02/05 18:41:25 ucko * GetEntryPoint: Darwin may or may not need a leading underscore, so try * it both ways. * * Revision 1.18 2003/12/09 13:06:44 kuznets * Supported dll base name in entry point resolution (CDllResolver) * * Revision 1.17 2003/12/01 16:39:15 kuznets * CDllResolver changed to try all entry points * (prev. version stoped on first successfull). * * Revision 1.16 2003/11/19 13:50:42 ivanov * GetEntryPoint() revamp: added GetEntryPoin_[Func|Data]() * * Revision 1.15 2003/11/12 17:40:54 kuznets * + CDllResolver::Unload() * * Revision 1.14 2003/11/10 15:28:46 kuznets * Fixed misprint * * Revision 1.13 2003/11/10 15:05:04 kuznets * Reflecting changes in hpp file * * Revision 1.12 2003/11/06 13:00:12 kuznets * +CDllResolver * * Revision 1.11 2002/12/19 20:27:09 ivanov * Added DLL name to an exception description in the x_ThrowException() * * Revision 1.10 2002/09/19 20:05:42 vasilche * Safe initialization of static mutexes * * Revision 1.9 2002/07/15 18:17:24 gouriano * renamed CNcbiException and its descendents * * Revision 1.8 2002/07/11 14:18:26 gouriano * exceptions replaced by CNcbiException-type ones * * Revision 1.7 2002/07/01 16:44:14 ivanov * Added Darwin specific: use leading underscores in entry names * * Revision 1.6 2002/05/28 20:01:20 vakatov * Typo fixed * * Revision 1.5 2002/05/23 22:24:07 ucko * Handle the absence of <dlfcn.h> better. * * Revision 1.4 2002/04/11 21:08:02 ivanov * CVS log moved to end of the file * * Revision 1.3 2002/03/25 18:10:00 ucko * Make errmsg const to accommodate platforms (FreeBSD at least) where * dlerror returns const char*. * * Revision 1.2 2002/01/16 18:48:57 ivanov * Added new constructor and related "basename" rules for DLL names. * Polished source code. * * Revision 1.1 2002/01/15 19:05:28 ivanov * Initial revision * * =========================================================================== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -