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 = s_instances.find (
f);
118 if (p != s_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 *>
174#if defined (HAVE_DLOPEN_API)
180 octave_dlopen_shlib (
const std::string&
f);
182 OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (octave_dlopen_shlib)
184 ~octave_dlopen_shlib ();
186 void * search (
const std::string& name,
194 bool is_open ()
const
196 return (m_search_all_loaded || m_library !=
nullptr);
204octave_dlopen_shlib::octave_dlopen_shlib (
const std::string&
f)
213# if defined (RTLD_NOW)
219# if defined (RTLD_GLOBAL)
220 flags |= RTLD_GLOBAL;
229 m_library = dlopen (
m_file.c_str (), flags);
233 const char *msg = dlerror ();
236 (*current_liboctave_error_handler)
237 (
"%s: failed to load\nIncompatible version or missing dependency?"
238 "\n%s",
m_file.c_str (), msg);
241 (
"%s: failed to load\nIncompatible version or missing dependency?",
246octave_dlopen_shlib::~octave_dlopen_shlib ()
253octave_dlopen_shlib::search (
const std::string& name,
256 void *function =
nullptr;
259 (*current_liboctave_error_handler)
260 (
"shared library %s is not open", m_file.c_str ());
262 std::string sym_name = name;
265 sym_name = mangler (name);
267 if (m_search_all_loaded)
268 function = dlsym (RTLD_DEFAULT, sym_name.c_str ());
270 function = dlsym (m_library, sym_name.c_str ());
275#elif defined (HAVE_LOADLIBRARY_API)
281 octave_w32_shlib (
const std::string&
f);
283 OCTAVE_DISABLE_COPY_MOVE (octave_w32_shlib)
285 ~octave_w32_shlib ();
287 void * search (
const std::string& name,
291 void * global_search (
const std::string& sym_name);
293 bool is_open ()
const
295 return (m_search_all_loaded || m_handle !=
nullptr);
303octave_w32_shlib::octave_w32_shlib (
const std::string&
f)
312 std::string dir = sys::file_ops::dirname (
f);
313 std::wstring wdir = sys::u8_to_wstring (dir);
314 SetDllDirectoryW (dir.empty ()
315 ?
nullptr : wdir.c_str ());
317 std::wstring wfile = sys::u8_to_wstring (
m_file);
318 m_handle = LoadLibraryW (wfile.c_str ());
320 SetDllDirectoryW (
nullptr);
324 DWORD last_error = GetLastError ();
326 wchar_t *error_text =
nullptr;
327 FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |
328 FORMAT_MESSAGE_ALLOCATE_BUFFER |
329 FORMAT_MESSAGE_IGNORE_INSERTS,
331 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
332 reinterpret_cast <wchar_t *
> (&error_text), 0,
nullptr);
334 std::ostringstream err_str;
335 err_str <<
"opening the library '" <<
m_file <<
"' failed (error "
336 << last_error <<
"): ";
337 if (error_text !=
nullptr)
339 err_str << sys::u8_from_wstring (error_text);
340 LocalFree (error_text);
343 err_str <<
"Unknown error.";
345 (*current_liboctave_error_handler) (
"%s", err_str.str ().c_str ());
349octave_w32_shlib::~octave_w32_shlib ()
352 FreeLibrary (m_handle);
356octave_w32_shlib::global_search (
const std::string& sym_name)
358 void *function =
nullptr;
360 HANDLE proc = GetCurrentProcess ();
363 (*current_liboctave_error_handler)
364 (
"Unable to get handle to own process.");
366 std::size_t lib_num = 64;
367 std::size_t size_lib =
sizeof (HMODULE);
369 DWORD bytes_all_libs;
373 h_libs =
static_cast<HMODULE *
> (
malloc (size_lib*lib_num));
374 got_libs = EnumProcessModules (proc, h_libs, size_lib*lib_num,
377 while (((size_lib*lib_num) < bytes_all_libs) && ii++ < 3)
379 lib_num = bytes_all_libs / size_lib;
380 h_libs =
static_cast<HMODULE *
> (realloc (h_libs, bytes_all_libs));
381 got_libs = EnumProcessModules (proc, h_libs, bytes_all_libs,
387 for (std::size_t i = 0; i < (bytes_all_libs / size_lib); i++)
390 function =
reinterpret_cast<void *
>
391 (GetProcAddress (h_libs[i], sym_name.c_str ()));
405octave_w32_shlib::search (
const std::string& name,
408 void *function =
nullptr;
410 if (! m_search_all_loaded && ! is_open ())
411 (*current_liboctave_error_handler)
412 (
"shared library %s is not open", m_file.c_str ());
414 std::string sym_name = name;
417 sym_name = mangler (name);
419 if (m_search_all_loaded)
420 function = global_search (sym_name);
422 function =
reinterpret_cast<void *
> (GetProcAddress (m_handle,
433#if defined (HAVE_DLOPEN_API)
434 return new octave_dlopen_shlib (
f);
435#elif defined (HAVE_LOADLIBRARY_API)
436 return new octave_w32_shlib (
f);
438 (*current_liboctave_error_handler)
439 (
"support for dynamically loaded libraries was unavailable or disabled when liboctave was built");
443OCTAVE_END_NAMESPACE(octave)
bool remove_fcn_name(const std::string &)
static std::map< std::string, dynlib_rep * > s_instances
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
F77_RET_T const F77_DBLE const F77_DBLE * f
int release_unreferenced_dynamic_libraries()
std::list< dynamic_library > possibly_unreferenced_dynamic_libraries