1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29
30 #include "file-ops.h"
31 #include "oct-shlib.h"
32
33 #include "defaults.h"
34 #include "dynamic-ld.h"
35 #include "error.h"
36 #include "interpreter-private.h"
37 #include "ovl.h"
38 #include "ov-dld-fcn.h"
39 #include "ov.h"
40
41
42 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_dld_function,
43 "dynamically-linked function",
44 "dynamically-linked function");
45
octave_dld_function(octave_builtin::fcn ff,const octave::dynamic_library & shl,const std::string & nm,const std::string & ds)46 octave_dld_function::octave_dld_function
47 (octave_builtin::fcn ff, const octave::dynamic_library& shl,
48 const std::string& nm, const std::string& ds)
49 : octave_builtin (ff, nm, ds), sh_lib (shl)
50 {
51 mark_fcn_file_up_to_date (time_parsed ());
52
53 std::string file_name = fcn_file_name ();
54
55 static const std::string canonical_oct_file_dir
56 = octave::sys::canonicalize_file_name (octave::config::oct_file_dir ());
57 static const std::string oct_file_dir
58 = canonical_oct_file_dir.empty () ? octave::config::oct_file_dir ()
59 : canonical_oct_file_dir;
60
61 system_fcn_file
62 = (! file_name.empty ()
63 && oct_file_dir == file_name.substr (0, oct_file_dir.length ()));
64 }
65
octave_dld_function(octave_builtin::meth mm,const octave::dynamic_library & shl,const std::string & nm,const std::string & ds)66 octave_dld_function::octave_dld_function
67 (octave_builtin::meth mm, const octave::dynamic_library& shl,
68 const std::string& nm, const std::string& ds)
69 : octave_builtin (mm, nm, ds), sh_lib (shl)
70 {
71 mark_fcn_file_up_to_date (time_parsed ());
72
73 std::string file_name = fcn_file_name ();
74
75 static const std::string canonical_oct_file_dir
76 = octave::sys::canonicalize_file_name (octave::config::oct_file_dir ());
77 static const std::string oct_file_dir
78 = canonical_oct_file_dir.empty () ? octave::config::oct_file_dir ()
79 : canonical_oct_file_dir;
80
81 system_fcn_file
82 = (! file_name.empty ()
83 && oct_file_dir == file_name.substr (0, oct_file_dir.length ()));
84 }
85
~octave_dld_function(void)86 octave_dld_function::~octave_dld_function (void)
87 {
88 octave::dynamic_loader& dyn_loader
89 = octave::__get_dynamic_loader__ ("~octave_dld_function");
90
91 dyn_loader.remove_oct (my_name, sh_lib);
92 }
93
94 std::string
fcn_file_name(void) const95 octave_dld_function::fcn_file_name (void) const
96 {
97 return sh_lib.file_name ();
98 }
99
100 octave::sys::time
time_parsed(void) const101 octave_dld_function::time_parsed (void) const
102 {
103 return sh_lib.time_loaded ();
104 }
105
106 // Note: this wrapper around the octave_dld_function constructor is
107 // necessary to work around a MSVC limitation handling in
108 // virtual destructors that prevents unloading a dynamic module
109 // before *all* objects (of class using a virtual dtor) have
110 // been fully deleted; indeed, MSVC attaches auto-generated code
111 // (scalar deleting destructor) to objects created in a dynamic
112 // module, and this code will be executed in the dynamic module
113 // context at object deletion; unloading the dynamic module
114 // before objects have been deleted will make the "delete" code
115 // of objects to point to an invalid code segment.
116
117 octave_dld_function*
create(octave_builtin::fcn ff,const octave::dynamic_library & shl,const std::string & nm,const std::string & ds)118 octave_dld_function::create (octave_builtin::fcn ff,
119 const octave::dynamic_library& shl,
120 const std::string& nm, const std::string& ds)
121 {
122 return new octave_dld_function (ff, shl, nm, ds);
123 }
124
125 octave_dld_function*
create(octave_builtin::meth mm,const octave::dynamic_library & shl,const std::string & nm,const std::string & ds)126 octave_dld_function::create (octave_builtin::meth mm,
127 const octave::dynamic_library& shl,
128 const std::string& nm, const std::string& ds)
129 {
130 return new octave_dld_function (mm, shl, nm, ds);
131 }
132