CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
linux_dynamiclib.hpp
1#ifndef CPPAD_CG_LINUX_DYNAMICLIB_INCLUDED
2#define CPPAD_CG_LINUX_DYNAMICLIB_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2012 Ciengis
6 * Copyright (C) 2018 Joao Leal
7 *
8 * CppADCodeGen is distributed under multiple licenses:
9 *
10 * - Eclipse Public License Version 1.0 (EPL1), and
11 * - GNU General Public License Version 3 (GPL3).
12 *
13 * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
14 * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
15 * ----------------------------------------------------------------------------
16 * Author: Joao Leal
17 */
18#if CPPAD_CG_SYSTEM_LINUX
19
20#include <typeinfo>
21#include <dlfcn.h>
22
23namespace CppAD {
24namespace cg {
25
32template<class Base>
33class LinuxDynamicLib : public DynamicLib<Base> {
34protected:
35 const std::string _dynLibName;
37 void* _dynLibHandle;
38 std::set<LinuxDynamicLibModel<Base>*> _models;
39public:
40
41 explicit LinuxDynamicLib(std::string dynLibName,
42 int dlOpenMode = RTLD_NOW) :
43 _dynLibName(std::move(dynLibName)),
44 _dynLibHandle(nullptr) {
45
46 std::string path;
47 if (_dynLibName[0] == '/') {
48 path = _dynLibName; // absolute path
49 } else if (!(_dynLibName[0] == '.' && _dynLibName[1] == '/') &&
50 !(_dynLibName[0] == '.' && _dynLibName[1] == '.')) {
51 path = "./" + _dynLibName; // relative path
52 } else {
53 path = _dynLibName;
54 }
55
56 // load the dynamic library
57 _dynLibHandle = dlopen(path.c_str(), dlOpenMode);
58 CPPADCG_ASSERT_KNOWN(_dynLibHandle != nullptr, ("Failed to dynamically load library '" + _dynLibName + "': " + dlerror()).c_str())
59
60 // validate the dynamic library
61 this->validate();
62 }
63
64 LinuxDynamicLib(const LinuxDynamicLib&) = delete;
65 LinuxDynamicLib& operator=(const LinuxDynamicLib&) = delete;
66
67 virtual std::unique_ptr<LinuxDynamicLibModel<Base>> modelLinuxDyn(const std::string& modelName) {
68 std::unique_ptr<LinuxDynamicLibModel<Base>> m;
69 auto it = this->_modelNames.find(modelName);
70 if (it == this->_modelNames.end()) {
71 return m;
72 }
73 m.reset(new LinuxDynamicLibModel<Base> (this, modelName));
74 _models.insert(m.get());
75 return m;
76 }
77
78 std::unique_ptr<FunctorGenericModel<Base>> modelFunctor(const std::string& modelName) override final {
79 return std::unique_ptr<FunctorGenericModel<Base>>(modelLinuxDyn(modelName).release());
80 }
81
82 void* loadFunction(const std::string& functionName, bool required = true) override {
83 void* functor = dlsym(_dynLibHandle, functionName.c_str());
84
85 if (required) {
86 char *err = dlerror();
87 if (err != nullptr)
88 throw CGException("Failed to load function '", functionName, "': ", err);
89 }
90
91 return functor;
92 }
93
94 virtual ~LinuxDynamicLib() {
95 for (LinuxDynamicLibModel<Base>* model : _models) {
96 model->modelLibraryClosed();
97 }
98
99 if (_dynLibHandle != nullptr) {
100 if(this->_onClose != nullptr) {
101 (*this->_onClose)();
102 }
103
104 dlclose(_dynLibHandle);
105 _dynLibHandle = nullptr;
106 }
107 }
108
109protected:
110
111 virtual void destroyed(LinuxDynamicLibModel<Base>* model) {
112 _models.erase(model);
113 }
114
115 friend class LinuxDynamicLibModel<Base>;
116
117};
118
119} // END cg namespace
120} // END CppAD namespace
121
122#endif
123#endif