26#if defined (HAVE_CONFIG_H)
35#if defined (HAVE_DLOPEN_API)
36# if defined (HAVE_DLFCN_H)
39 extern void * dlopen (
const char *,
int);
40 extern const char * dlerror ();
41 extern void * dlsym (
void *,
const char *);
42 extern int dlclose (
void *);
44#elif defined (HAVE_LOADLIBRARY_API)
45# define WIN32_LEAN_AND_MEAN 1
57#if defined (HAVE_LOADLIBRARY_API)
80 : m_count (1), m_fcn_names (), m_file (
f), m_time_loaded (),
81 m_search_all_loaded (false)
86 (*current_liboctave_warning_with_id_handler)
87 (
"Octave:future-time-stamp",
88 "time stamp for file '%s' is in the future",
m_file.c_str ());
94 sys::file_stat fs (m_file);
95 return (fs && fs.is_newer (m_time_loaded));
102 sys::file_stat fs (m_file);
103 if (fs && fs.is_newer (m_time_loaded))
105 m_time_loaded = fs.mtime ();
107 (*current_liboctave_warning_with_id_handler)
108 (
"Octave:library-reload",
109 "library %s not reloaded due to existing references", m_file.c_str ());
117 std::map<std::string, dynlib_rep *>::iterator p = instances ().find (
f);
118 if (p != instances ().end ())
126 retval = new_instance (
f);
131std::list<std::string>
134 std::list<std::string> retval;
136 for (
const auto& p : m_fcn_names)
137 retval.push_back (p.first);
145 auto p = m_fcn_names.find (name);
147 if (p == m_fcn_names.end ())
148 m_fcn_names[name] = 1;
158 auto p = m_fcn_names.find (fcn_name);
160 if (p != m_fcn_names.end () && --(p->second) == 0)
162 m_fcn_names.erase (fcn_name);
169std::map<std::string, dynamic_library::dynlib_rep *>&
185 static auto *s_instances =
new std::map<std::string, dynlib_rep *> ();
191#if defined (HAVE_DLOPEN_API)
197 octave_dlopen_shlib (
const std::string&
f);
199 OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (octave_dlopen_shlib)
201 ~octave_dlopen_shlib ();
203 void * search (
const std::string& name,
211 bool is_open ()
const
213 return (m_search_all_loaded || m_library !=
nullptr);
221octave_dlopen_shlib::octave_dlopen_shlib (
const std::string&
f)
230# if defined (RTLD_NOW)
236# if defined (RTLD_GLOBAL)
237 flags |= RTLD_GLOBAL;
246 m_library = dlopen (
m_file.c_str (), flags);
250 const char *msg = dlerror ();
253 (*current_liboctave_error_handler)
254 (
"%s: failed to load\nIncompatible version or missing dependency?"
255 "\n%s",
m_file.c_str (), msg);
258 (
"%s: failed to load\nIncompatible version or missing dependency?",
263octave_dlopen_shlib::~octave_dlopen_shlib ()
270octave_dlopen_shlib::search (
const std::string& name,
273 void *function =
nullptr;
276 (*current_liboctave_error_handler)
277 (
"shared library %s is not open", m_file.c_str ());
279 std::string sym_name = name;
282 sym_name = mangler (name);
284 if (m_search_all_loaded)
285 function = dlsym (RTLD_DEFAULT, sym_name.c_str ());
287 function = dlsym (m_library, sym_name.c_str ());
292#elif defined (HAVE_LOADLIBRARY_API)
298 octave_w32_shlib (
const std::string&
f);
300 OCTAVE_DISABLE_COPY_MOVE (octave_w32_shlib)
302 ~octave_w32_shlib ();
304 void * search (
const std::string& name,
308 void * global_search (
const std::string& sym_name);
310 bool is_open ()
const
312 return (m_search_all_loaded || m_handle !=
nullptr);
320octave_w32_shlib::octave_w32_shlib (
const std::string&
f)
329 std::string dir = sys::file_ops::dirname (
f);
330 std::wstring wdir = sys::u8_to_wstring (dir);
331 SetDllDirectoryW (dir.empty ()
332 ?
nullptr : wdir.c_str ());
334 std::wstring wfile = sys::u8_to_wstring (
m_file);
335 m_handle = LoadLibraryW (wfile.c_str ());
337 SetDllDirectoryW (
nullptr);
341 DWORD last_error = GetLastError ();
343 wchar_t *error_text =
nullptr;
344 FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |
345 FORMAT_MESSAGE_ALLOCATE_BUFFER |
346 FORMAT_MESSAGE_IGNORE_INSERTS,
348 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
349 reinterpret_cast<wchar_t *
> (&error_text), 0,
nullptr);
351 std::ostringstream err_str;
352 err_str <<
"opening the library '" <<
m_file <<
"' failed (error "
353 << last_error <<
"): ";
354 if (error_text !=
nullptr)
356 err_str << sys::u8_from_wstring (error_text);
357 LocalFree (error_text);
360 err_str <<
"Unknown error.";
362 (*current_liboctave_error_handler) (
"%s", err_str.str ().c_str ());
366octave_w32_shlib::~octave_w32_shlib ()
369 FreeLibrary (m_handle);
373octave_w32_shlib::global_search (
const std::string& sym_name)
375 void *function =
nullptr;
377 HANDLE proc = GetCurrentProcess ();
380 (*current_liboctave_error_handler)
381 (
"Unable to get handle to own process.");
383 std::size_t lib_num = 64;
384 std::size_t size_lib =
sizeof (HMODULE);
386 DWORD bytes_all_libs;
390 h_libs =
static_cast<HMODULE *
> (
malloc (size_lib*lib_num));
391 got_libs = EnumProcessModules (proc, h_libs, size_lib*lib_num,
394 while (((size_lib*lib_num) < bytes_all_libs) && ii++ < 3)
396 lib_num = bytes_all_libs / size_lib;
397 h_libs =
static_cast<HMODULE *
> (realloc (h_libs, bytes_all_libs));
398 got_libs = EnumProcessModules (proc, h_libs, bytes_all_libs,
404 for (std::size_t i = 0; i < (bytes_all_libs / size_lib); i++)
407 function =
reinterpret_cast<void *
>
408 (GetProcAddress (h_libs[i], sym_name.c_str ()));
422octave_w32_shlib::search (
const std::string& name,
425 void *function =
nullptr;
427 if (! m_search_all_loaded && ! is_open ())
428 (*current_liboctave_error_handler)
429 (
"shared library %s is not open", m_file.c_str ());
431 std::string sym_name = name;
434 sym_name = mangler (name);
436 if (m_search_all_loaded)
437 function = global_search (sym_name);
439 function =
reinterpret_cast<void *
> (GetProcAddress (m_handle,
450#if defined (HAVE_DLOPEN_API)
451 return new octave_dlopen_shlib (
f);
452#elif defined (HAVE_LOADLIBRARY_API)
453 return new octave_w32_shlib (
f);
455 (*current_liboctave_error_handler)
456 (
"support for dynamically loaded libraries was unavailable or disabled when liboctave was built");
460OCTAVE_END_NAMESPACE(octave)
static std::map< std::string, dynlib_rep * > & instances()
bool remove_fcn_name(const std::string &)
void add_fcn_name(const std::string &)
static dynlib_rep * new_instance(const std::string &f)
bool is_out_of_date() const
static dynlib_rep * get_instance(const std::string &f, bool fake)
std::list< std::string > function_names() const
refcount< octave_idx_type > m_count
std::function< std::string(const std::string &)> name_mangler
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
int release_unreferenced_dynamic_libraries()
std::list< dynamic_library > possibly_unreferenced_dynamic_libraries
F77_RET_T const F77_DBLE const F77_DBLE * f