A little refactoring - central place for DLL/.so path detection

This commit is contained in:
Matthias Koefferlein 2018-07-29 10:20:48 +02:00
parent 3d7bd0f32d
commit 3fb568671d
4 changed files with 73 additions and 96 deletions

View File

@ -95,46 +95,11 @@ static PluginDescriptor load_plugin (const std::string &pp)
return desc;
}
/**
* @brief Gets the path to the current module
*/
static std::string
get_module_path ()
{
#if defined(_WIN32)
HMODULE h_module = NULL;
if (GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR) &init, &h_module)) {
wchar_t buffer[MAX_PATH];
int len;
if ((len = GetModuleFileName(h_module, buffer, MAX_PATH)) > 0) {
return tl::absolute_file_path (tl::to_string (std::wstring (buffer, 0, len)));
}
}
// no way to get module file path
return std::string ();
#else
Dl_info info = { };
if (dladdr ((void *) &init, &info)) {
return tl::absolute_file_path (tl::to_string_from_local (info.dli_fname));
} else {
tl::warn << tl::to_string (tr ("Unable to get path of db library (as basis for loading db_plugins)"));
return std::string ();
}
#endif
}
void init (const std::vector<std::string> &_paths)
{
std::vector<std::string> paths = _paths;
if (paths.empty ()) {
std::string module_path = get_module_path ();
std::string module_path = tl::get_module_path ((void *) &init);
if (! module_path.empty ()) {
paths.push_back (tl::absolute_path (module_path));
}
@ -154,6 +119,8 @@ void init (const std::vector<std::string> &_paths)
const char *db_plugin_dir = "db_plugins";
std::string pp = tl::combine_path (*p, db_plugin_dir);
tl::log << tl::sprintf (tl::to_string (tr ("Scanning '%s'' for plugins ..")), pp);
std::vector<std::string> ee = tl::dir_entries (pp, true, false);
tl::GlobPattern pattern;

View File

@ -26,6 +26,7 @@
#include "tlLog.h"
#include "tlString.h"
#include "tlFileUtils.h"
#include "tlGlobPattern.h"
#ifdef _WIN32
# include <windows.h>
@ -95,47 +96,11 @@ void load_plugin (const std::string &pp)
s_plugins.push_back (do_load_plugin (pp));
}
/**
* @brief Gets the path to the current module
*/
static std::string
get_module_path ()
{
#if defined(_WIN32)
HMODULE h_module = NULL;
if (GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR) &init, &h_module)) {
wchar_t buffer[MAX_PATH];
int len;
if ((len = GetModuleFileName(h_module, buffer, MAX_PATH)) > 0) {
QFileInfo fi (QString::fromUtf16 ((const ushort *) buffer, len));
return tl::to_string (fi.absolutePath ());
}
}
// no way to get module file path
return std::string ();
#else
Dl_info info = { };
if (dladdr ((void *) &init, &info)) {
return tl::absolute_file_path (tl::to_string_from_local (info.dli_fname));
} else {
tl::warn << tl::to_string (tr ("Unable to get path of lay library (as basis for loading lay_plugins)"));
return std::string ();
}
#endif
}
void init (const std::vector<std::string> &_paths)
{
std::vector<std::string> paths = _paths;
if (paths.empty ()) {
std::string module_path = get_module_path ();
std::string module_path = tl::get_module_path ((void *) &init);
if (! module_path.empty ()) {
paths.push_back (module_path);
}
@ -151,38 +116,41 @@ void init (const std::vector<std::string> &_paths)
for (std::vector<std::string>::const_iterator p = paths.begin (); p != paths.end (); ++p) {
// look next to the db library, but in "lay_plugins" directory
const char *db_plugin_dir = "lay_plugins";
std::string pp = tl::to_string (QDir (tl::to_qstring (*p)).filePath (QString::fromUtf8 (db_plugin_dir)));
// look next to the lay library, but in "lay_plugins" directory
const char *lay_plugin_dir = "lay_plugins";
std::string pp = tl::combine_path (*p, lay_plugin_dir);
QStringList name_filters;
tl::log << tl::sprintf (tl::to_string (tr ("Scanning '%s'' for plugins ..")), pp);
std::vector<std::string> ee = tl::dir_entries (pp, true, false);
tl::GlobPattern pattern;
#if defined(_WIN32)
name_filters << QString::fromUtf8 ("*.dll");
pattern.set_case_sensitive (false);
pattern = std::string ("*.dll");
#else
name_filters << QString::fromUtf8 ("*.so");
pattern = std::string ("*.so");
#endif
QStringList inst_modules = QDir (tl::to_qstring (pp)).entryList (name_filters);
inst_modules.sort ();
std::vector<std::string> inst_modules;
for (std::vector<std::string>::const_iterator e = ee.begin (); e != ee.end (); ++e) {
if (pattern.match (*e)) {
inst_modules.push_back (*e);
}
}
for (QStringList::const_iterator im = inst_modules.begin (); im != inst_modules.end (); ++im) {
std::sort (inst_modules.begin (), inst_modules.end ());
QFileInfo layp_file (tl::to_qstring (pp), *im);
if (layp_file.exists () && layp_file.isReadable ()) {
std::string mn = tl::to_string (layp_file.fileName ());
if (modules.find (mn) == modules.end ()) {
std::string m = tl::to_string (layp_file.absoluteFilePath ());
try {
s_plugins.push_back (do_load_plugin (m));
modules.insert (mn);
} catch (tl::Exception (&ex)) {
tl::error << ex.msg ();
}
for (std::vector<std::string>::const_iterator im = inst_modules.begin (); im != inst_modules.end (); ++im) {
std::string imp = tl::combine_path (pp, *im);
if (modules.find (*im) == modules.end ()) {
try {
s_plugins.push_back (do_load_plugin (imp));
modules.insert (*im);
} catch (tl::Exception (&ex)) {
tl::error << ex.msg ();
}
}
}

View File

@ -38,6 +38,10 @@
# include <libproc.h>
#endif
#if !defined(_WIN32)
# include <dlfcn.h>
#endif
namespace tl
{
@ -790,4 +794,36 @@ get_inst_path ()
return s_inst_path;
}
std::string
get_module_path (void *addr)
{
#if defined(_WIN32)
HMODULE h_module = NULL;
if (GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR) addr, &h_module)) {
wchar_t buffer[MAX_PATH];
int len;
if ((len = GetModuleFileName(h_module, buffer, MAX_PATH)) > 0) {
return tl::absolute_file_path (tl::to_string (std::wstring (buffer, 0, len)));
}
}
// no way to get module file path
return std::string ();
#else
Dl_info info = { };
if (dladdr (addr, &info)) {
return tl::absolute_file_path (tl::to_string_from_local (info.dli_fname));
} else {
tl::warn << tl::to_string (tr ("Unable to get path of db library (as basis for loading db_plugins)"));
return std::string ();
}
#endif
}
}

View File

@ -178,6 +178,12 @@ std::vector<std::string> TL_PUBLIC split_path (const std::string &p, bool keep_l
*/
std::string TL_PUBLIC get_inst_path ();
/**
* @brief Gets the absolute path of the module (DLL/.so) which contains the given address
* "address" is supposed to be the address of a function inside the module.
*/
std::string TL_PUBLIC get_module_path (void *addr);
}
#endif