diff --git a/applications/test/dynamicLibrary/Make/files b/applications/test/dynamicLibrary/Make/files
new file mode 100644
index 0000000000..54ed5e99bc
--- /dev/null
+++ b/applications/test/dynamicLibrary/Make/files
@@ -0,0 +1,3 @@
+Test-dynamicLibrary.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-dynamicLibrary
diff --git a/applications/test/dynamicLibrary/Make/options b/applications/test/dynamicLibrary/Make/options
new file mode 100644
index 0000000000..75c7356f1c
--- /dev/null
+++ b/applications/test/dynamicLibrary/Make/options
@@ -0,0 +1,2 @@
+EXE_INC =
+EXE_LIBS =
diff --git a/applications/test/dynamicLibrary/Test-dynamicLibrary.C b/applications/test/dynamicLibrary/Test-dynamicLibrary.C
new file mode 100644
index 0000000000..ee7009b961
--- /dev/null
+++ b/applications/test/dynamicLibrary/Test-dynamicLibrary.C
@@ -0,0 +1,143 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | www.openfoam.com
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2020 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+Application
+ Test-dynamicLibrary
+
+Description
+ Test loading/unloading of libraries
+
+\*---------------------------------------------------------------------------*/
+
+#include "argList.H"
+#include "profiling.H"
+#include "DynamicList.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char *argv[])
+{
+ argList::addNote("Low-level test of library load/unload");
+
+ profiling::disable(); // No profiling output
+ argList::noBanner();
+ argList::noParallel();
+ argList::removeOption("case");
+ argList::removeOption("noFunctionObjects");
+ argList::addBoolOption("no-close", "Skip dlclose");
+ argList::addBoolOption("quiet", "Disable verbosity");
+
+ argList::addArgument("lib...");
+ argList::noMandatoryArgs(); // Arguments are optional
+
+ argList args(argc, argv, false, true);
+
+ const bool noClose = args.found("no-close");
+ const bool verbose = !args.found("quiet");
+
+ //- Pointers to the loaded libraries
+ DynamicList libPtrs_;
+
+ //- Names of loaded libraries, or of libraries to be loaded
+ DynamicList libNames_;
+
+ label nbad = 0;
+ wordHashSet loaded;
+
+ for (int argi = 1; argi < args.size(); ++argi)
+ {
+ const fileName libName(fileName::validate(args[argi]));
+
+ if (libName.empty())
+ {
+ continue;
+ }
+
+ void* ptr = Foam::dlOpen(libName, false);
+
+ if (!ptr)
+ {
+ ++nbad;
+ }
+ else
+ {
+ libPtrs_.append(ptr);
+ libNames_.append(libName);
+
+ if (verbose)
+ {
+ const word addr(Foam::name(ptr));
+
+ if (loaded.insert(addr))
+ {
+ InfoErr << "Can load " << libName << nl;
+ }
+ else
+ {
+ InfoErr << "Already loaded " << libName << nl;
+ }
+ }
+ }
+ }
+
+ if (!noClose)
+ {
+ forAllReverse(libPtrs_, i)
+ {
+ void* ptr = libPtrs_[i];
+
+ if (ptr == nullptr)
+ {
+ libNames_[i].clear();
+ continue;
+ }
+
+ const bool ok = Foam::dlClose(ptr);
+
+ if (verbose)
+ {
+ if (ok)
+ {
+ InfoErr << "Closed ";
+ }
+ else
+ {
+ InfoErr << "Failed closing ";
+ }
+
+ InfoErr
+ << libNames_[i]
+ << " with handle " << Foam::name(ptr) << nl;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/Time/Time.C b/src/OpenFOAM/db/Time/Time.C
index cccda67da8..dbc1c8214c 100644
--- a/src/OpenFOAM/db/Time/Time.C
+++ b/src/OpenFOAM/db/Time/Time.C
@@ -471,7 +471,7 @@ Foam::Time::Time
if (enableLibs)
{
- libs_.open(controlDict_, "libs");
+ libs_.open("libs", controlDict_);
}
// Explicitly set read flags on objectRegistry so anything constructed
@@ -553,12 +553,9 @@ Foam::Time::Time
// Libraries
//
// * enable by default unless '-no-libs' option was used
- if (!args.found("no-libs"))
+ if (enableLibs && !args.found("no-libs"))
{
- if (enableLibs)
- {
- libs_.open(controlDict_, "libs");
- }
+ libs_.open("libs", controlDict_);
}
// Explicitly set read flags on objectRegistry so anything constructed
@@ -634,7 +631,7 @@ Foam::Time::Time
if (enableLibs)
{
- libs_.open(controlDict_, "libs");
+ libs_.open("libs", controlDict_);
}
@@ -708,7 +705,7 @@ Foam::Time::Time
if (enableLibs)
{
- libs_.open(controlDict_, "libs");
+ libs_.open("libs", controlDict_);
}
setMonitoring(); // for profiling etc
diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
index 72a1f92778..2fd1c3c78b 100644
--- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
+++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C
@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
- Copyright (C) 2018-2019 OpenCFD Ltd.
+ Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -145,18 +145,13 @@ Foam::functionEntries::codeStream::getFunction
if (isA(topDict))
{
- // Cached access to dl libs. Guarantees clean up upon destruction
- // of Time.
- dlLibraryTable& dlLibs = libs(parentDict);
- if (dlLibs.open(libPath, false))
- {
- lib = dlLibs.findLibrary(libPath);
- }
+ // Cached access to libs, with cleanup upon termination
+ lib = libs(parentDict).open(libPath, false);
}
else
{
// Uncached opening of libPath. Do not complain if cannot be loaded
- lib = dlOpen(libPath, false);
+ lib = Foam::dlOpen(libPath, false);
}
}
@@ -299,14 +294,13 @@ Foam::functionEntries::codeStream::getFunction
if (isA(topDict))
{
- // Cached access to dl libs. Guarantees clean up upon destruction
- // of Time.
- dlLibraryTable& dlLibs = libs(parentDict);
-
+ // Cached access to libs, with cleanup upon termination
DebugPout
<< "Opening cached dictionary:" << libPath << endl;
- if (!dlLibs.open(libPath, false))
+ lib = libs(parentDict).open(libPath, false);
+
+ if (!lib)
{
FatalIOErrorInFunction(parentDict)
<< "Failed loading library " << libPath << nl
@@ -314,8 +308,6 @@ Foam::functionEntries::codeStream::getFunction
<< " in system/controlDict?"
<< exit(FatalIOError);
}
-
- lib = dlLibs.findLibrary(libPath);
}
else
{
@@ -323,7 +315,7 @@ Foam::functionEntries::codeStream::getFunction
DebugPout
<< "Opening uncached dictionary:" << libPath << endl;
- lib = dlOpen(libPath, true);
+ lib = Foam::dlOpen(libPath, true);
}
}
@@ -346,7 +338,7 @@ Foam::functionEntries::codeStream::getFunction
streamingFunctionType function =
reinterpret_cast
(
- dlSym(lib, dynCode.codeName())
+ Foam::dlSym(lib, dynCode.codeName())
);
diff --git a/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.C b/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.C
index c4429222cb..0f6cc586d9 100644
--- a/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.C
+++ b/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.C
@@ -98,12 +98,7 @@ void* Foam::codedBase::loadLibrary
{
// Avoid compilation by loading an existing library
- void* handle =
- (
- !libPath.empty() && libs().open(libPath, false)
- ? libs().findLibrary(libPath)
- : nullptr
- );
+ void* handle = libs().open(libPath, false);
if (!handle)
{
@@ -115,25 +110,9 @@ void* Foam::codedBase::loadLibrary
// Manual execution of code after loading.
// This is mandatory for codedBase.
- void* rawSymbol = dlSymFind(handle, funcName);
+ const bool ok = libs().loadHook(handle, funcName, false);
- if (rawSymbol)
- {
- loaderType fun = reinterpret_cast(rawSymbol);
-
- if (fun)
- {
- (*fun)(true); // force load
- }
- else
- {
- FatalIOErrorInFunction(context.dict())
- << "Failed symbol lookup " << funcName.c_str() << nl
- << "from " << libPath << nl
- << exit(FatalIOError);
- }
- }
- else
+ if (!ok)
{
FatalIOErrorInFunction(context.dict())
<< "Failed symbol lookup " << funcName.c_str() << nl
@@ -160,12 +139,7 @@ void Foam::codedBase::unloadLibrary
const dynamicCodeContext& context
) const
{
- void* handle =
- (
- !libPath.empty() && libs().open(libPath, false)
- ? libs().findLibrary(libPath)
- : nullptr
- );
+ void* handle = libs().open(libPath, false);
if (!handle)
{
@@ -175,23 +149,13 @@ void Foam::codedBase::unloadLibrary
// Manual execution of code before unloading.
// This is mandatory for codedBase.
- void* rawSymbol = dlSymFind(handle, funcName);
+ const bool ok = libs().unloadHook(handle, funcName, false);
- if (rawSymbol)
+ if (!ok)
{
- loaderType fun = reinterpret_cast(rawSymbol);
-
- if (fun)
- {
- (*fun)(false); // force unload
- }
- else
- {
- FatalIOErrorInFunction(context.dict())
- << "Failed symbol lookup " << funcName.c_str() << nl
- << "from " << libPath << nl
- << exit(FatalIOError);
- }
+ IOWarningInFunction(context.dict())
+ << "Failed looking up symbol " << funcName << nl
+ << "from " << libPath << nl;
}
if (!libs().close(libPath, false))
@@ -389,7 +353,7 @@ void Foam::codedBase::updateLibrary
unloadLibrary
(
oldLibPath_,
- dynamicCode::libraryBaseName(oldLibPath_),
+ dlLibraryTable::basename(oldLibPath_),
context
);
diff --git a/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.H b/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.H
index e0bae03e59..8f276553b2 100644
--- a/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.H
+++ b/src/OpenFOAM/db/dynamicLibrary/codedBase/codedBase.H
@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
- Copyright (C) 2016-2019 OpenCFD Ltd.
+ Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -75,13 +75,6 @@ class codedBase
mutable fileName oldLibPath_;
- // Data Types
-
- //- Global loader/unloader function type
- // Called with true on load, false on unload.
- typedef void (*loaderType)(bool);
-
-
// Private Member Functions
//- Load specified library and execute funcName(true)
diff --git a/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.C b/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.C
index 3fb1c99437..54b3feca21 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.C
+++ b/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.C
@@ -29,7 +29,15 @@ License
#include "dlLibraryTable.H"
#include "OSspecific.H"
#include "IOstreams.H"
-#include "int.H"
+
+// Could be constexpr in the header if required
+#ifdef __APPLE__
+ #define EXT_SO "dylib"
+#elif defined _WIN32
+ #define EXT_SO "dll"
+#else
+ #define EXT_SO "so"
+#endif
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@@ -38,6 +46,115 @@ namespace Foam
defineTypeNameAndDebug(dlLibraryTable, 0);
}
+std::unique_ptr Foam::dlLibraryTable::global_(nullptr);
+
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+Foam::word Foam::dlLibraryTable::basename(const fileName& libPath)
+{
+ word libName(libPath.nameLessExt());
+ libName.removeStart("lib"); // Remove leading 'lib' from name
+ return libName;
+}
+
+
+Foam::word Foam::dlLibraryTable::fullname(word libName)
+{
+ if (libName.empty())
+ {
+ return libName;
+ }
+
+ // Add leading 'lib' and trailing '.so'
+ return "lib" + libName.ext(EXT_SO);
+}
+
+
+Foam::dlLibraryTable& Foam::dlLibraryTable::libs()
+{
+ if (!global_)
+ {
+ global_.reset(new dlLibraryTable{});
+ }
+
+ return *global_;
+}
+
+
+bool Foam::dlLibraryTable::functionHook
+(
+ const bool load,
+ void* handle,
+ const std::string& funcName,
+ const bool verbose,
+ const std::string& context
+)
+{
+ if (!handle || funcName.empty())
+ {
+ return false;
+ }
+
+ bool ok = false;
+
+ void* symbol = Foam::dlSymFind(handle, funcName);
+
+ if (symbol)
+ {
+ // Execute loader/unloader code
+ try
+ {
+ loaderType fun = reinterpret_cast(symbol);
+
+ if (fun)
+ {
+ (*fun)(load);
+ ok = true;
+ }
+ }
+ catch (...)
+ {}
+ }
+
+ if (verbose && !ok)
+ {
+ auto& err = WarningInFunction
+ << "Failed symbol lookup " << funcName.c_str() << nl;
+
+ if (!context.empty())
+ {
+ err << "from " << context.c_str() << nl;
+ }
+ }
+
+ return ok;
+}
+
+
+bool Foam::dlLibraryTable::loadHook
+(
+ void* handle,
+ const std::string& funcName,
+ const bool verbose,
+ const std::string& context
+)
+{
+ return functionHook(true, handle, funcName, verbose, context);
+}
+
+
+bool Foam::dlLibraryTable::unloadHook
+(
+ void* handle,
+ const std::string& funcName,
+ const bool verbose,
+ const std::string& context
+)
+{
+ return functionHook(false, handle, funcName, verbose, context);
+}
+
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@@ -84,14 +201,39 @@ Foam::dlLibraryTable::dlLibraryTable
Foam::dlLibraryTable::dlLibraryTable
(
- const dictionary& dict,
- const word& libsEntry
+ std::initializer_list libNames,
+ bool verbose
)
{
- dlLibraryTable::open(dict, libsEntry);
+ dlLibraryTable::open(libNames, verbose);
}
+Foam::dlLibraryTable::dlLibraryTable
+(
+ const word& libsEntry,
+ const dictionary& dict,
+ bool verbose
+)
+{
+ fileNameList libNames;
+ dict.readIfPresent(libsEntry, libNames);
+ dlLibraryTable::open(libNames, verbose);
+}
+
+
+Foam::dlLibraryTable::dlLibraryTable
+(
+ const dictionary& dict,
+ const word& libsEntry,
+ bool verbose
+
+)
+:
+ dlLibraryTable(libsEntry, dict, verbose)
+{}
+
+
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::dlLibraryTable::~dlLibraryTable()
@@ -132,6 +274,30 @@ Foam::label Foam::dlLibraryTable::size() const
}
+Foam::List Foam::dlLibraryTable::loaded() const
+{
+ List list(libNames_.size());
+
+ label nLoaded = 0;
+
+ forAll(libNames_, i)
+ {
+ void* ptr = libPtrs_[i];
+ const fileName& libName = libNames_[i];
+
+ if (ptr != nullptr && !libName.empty())
+ {
+ list[nLoaded] = libName;
+ ++nLoaded;
+ }
+ }
+
+ list.resize(nLoaded);
+
+ return list;
+}
+
+
void Foam::dlLibraryTable::clear(bool verbose)
{
label nLoaded = 0;
@@ -231,12 +397,14 @@ bool Foam::dlLibraryTable::open(bool verbose)
forAll(libPtrs_, i)
{
+ void* ptr = libPtrs_[i];
const fileName& libName = libNames_[i];
- if (libPtrs_[i] == nullptr && !libName.empty())
+ if (ptr == nullptr && !libName.empty())
{
++nCand;
- void* ptr = openLibrary(libName, verbose);
+
+ ptr = openLibrary(libName, verbose);
if (ptr)
{
@@ -260,6 +428,7 @@ void* Foam::dlLibraryTable::open
bool verbose
)
{
+ // Handles empty name silently
void* ptr = openLibrary(libName, verbose);
if (ptr)
@@ -278,7 +447,34 @@ bool Foam::dlLibraryTable::open
bool verbose
)
{
- label nOpen = 0;
+ decltype(libNames.size()) nOpen = 0;
+
+ for (const fileName& libName : libNames)
+ {
+ const label index = libNames_.find(libName);
+
+ if (index >= 0 && libPtrs_[index] != nullptr)
+ {
+ // Already known and opened
+ ++nOpen;
+ }
+ else if (dlLibraryTable::open(libName, verbose))
+ {
+ ++nOpen;
+ }
+ }
+
+ return nOpen && nOpen == libNames.size();
+}
+
+
+bool Foam::dlLibraryTable::open
+(
+ std::initializer_list libNames,
+ bool verbose
+)
+{
+ decltype(libNames.size()) nOpen = 0;
for (const fileName& libName : libNames)
{
@@ -307,13 +503,19 @@ bool Foam::dlLibraryTable::close
{
const label index = libNames_.rfind(libName);
- if (index < 0)
+ if (index < 0 || libName.empty())
{
return false;
}
void* ptr = libPtrs_[index];
+ if (ptr == nullptr)
+ {
+ libNames_[index].clear();
+ return false;
+ }
+
DebugInFunction
<< "Closing " << libName
<< " with handle " << Foam::name(ptr) << nl;
@@ -323,7 +525,23 @@ bool Foam::dlLibraryTable::close
libPtrs_[index] = nullptr;
libNames_[index].clear();
- if (!ok && verbose)
+ if (ok)
+ {
+ // From man dlopen(3)
+ // ...
+ // a dynamically loaded shared object is not deallocated until
+ // dlclose() has been called on it as many times as dlopen()
+ // has succeeded on it.
+
+ // Handle aliased library names
+ for (label idx = 0; (idx = libPtrs_.find(ptr, idx)) >= 0; ++idx)
+ {
+ (void) Foam::dlClose(ptr);
+ libPtrs_[idx] = nullptr;
+ libNames_[idx].clear();
+ }
+ }
+ else if (verbose)
{
WarningInFunction
<< "Could not close " << libName << endl;
@@ -337,7 +555,7 @@ void* Foam::dlLibraryTable::findLibrary(const fileName& libName)
{
const label index = libNames_.rfind(libName);
- if (index < 0)
+ if (index < 0 || libName.empty())
{
return nullptr;
}
@@ -346,26 +564,29 @@ void* Foam::dlLibraryTable::findLibrary(const fileName& libName)
}
+bool Foam::dlLibraryTable::open
+(
+ const word& libsEntry,
+ const dictionary& dict,
+ bool verbose
+)
+{
+ fileNameList libNames;
+ return
+ (
+ dict.readIfPresent(libsEntry, libNames)
+ && dlLibraryTable::open(libNames, verbose)
+ );
+}
+
+
bool Foam::dlLibraryTable::open
(
const dictionary& dict,
const word& libsEntry
)
{
- fileNameList libNames;
- dict.readIfPresent(libsEntry, libNames);
-
- label nOpen = 0;
-
- for (const fileName& libName : libNames)
- {
- if (dlLibraryTable::open(libName)) // verbose = true
- {
- ++nOpen;
- }
- }
-
- return nOpen && nOpen == libNames.size();
+ return dlLibraryTable::open(libsEntry, dict, true); // verbose = true
}
@@ -381,7 +602,7 @@ Foam::Ostream& Foam::operator<<
os << token::BEGIN_LIST << nl;
- // Lengths of pointers/names are guaranteed interally to be identical
+ // Lengths of pointers/names are guaranteed internally to be identical
forAll(tbl.pointers(), i)
{
const void* ptr = tbl.pointers()[i];
diff --git a/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.H b/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.H
index b48f02f322..a89df8f908 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.H
+++ b/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTable.H
@@ -30,6 +30,10 @@ Class
Description
A table of dynamically loaded libraries.
+SeeAlso
+ Foam::dlOpen
+ Foam::dlClose
+
SourceFiles
dlLibraryTable.C
dlLibraryTableTemplates.C
@@ -40,7 +44,9 @@ SourceFiles
#define dlLibraryTable_H
#include "DynamicList.H"
+#include "fileName.H"
#include "InfoProxy.H"
+#include
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -57,15 +63,35 @@ Ostream& operator<<(Ostream& os, const InfoProxy& info);
class dlLibraryTable
{
+ // Static Data
+
+ //- Global singleton of dynamic libraries
+ static std::unique_ptr global_;
+
+
// Private Data
+ //- Pointers to the loaded libraries
DynamicList libPtrs_;
+ //- Names of loaded libraries, or of libraries to be loaded
DynamicList libNames_;
// Private Member Functions
+ //- Load/unload hook.
+ // \return true if the function was found and executed
+ static bool functionHook
+ (
+ const bool load, //!< true = on-load, false = on-unload
+ void* handle, //!< library handle
+ const std::string& funcName,
+ const bool verbose,
+ const std::string& context
+ );
+
+
//- Open specified library name and return pointer.
// Warning messages, but no additional side-effects.
void* openLibrary(const fileName& libName, bool verbose);
@@ -73,9 +99,17 @@ class dlLibraryTable
public:
- // Declare name of the class and its debug switch
+ // Public Data Types
+
+ //- Global loader/unloader function type (C-linkage)
+ // Called with true on load, false on unload.
+ typedef void (*loaderType)(bool);
+
+
+ //- Declare name of the class and its debug switch
ClassName("dlLibraryTable");
+
// Generated Methods
//- Default construct
@@ -96,22 +130,82 @@ public:
// Constructors
- //- Open specified libraries. Ignores duplicate names.
+ //- Open specified libraries, warn by default if problems occur
+ // Ignores duplicate names.
explicit dlLibraryTable
(
const UList& libNames,
bool verbose = true
);
- //- Open all libraries listed in the 'libsEntry' entry in the
- //- given dictionary. Verbose = true.
- dlLibraryTable(const dictionary& dict, const word& libsEntry);
+ //- Open specified libraries, warn by default if problems occur
+ // Ignores duplicate names.
+ explicit dlLibraryTable
+ (
+ std::initializer_list libNames,
+ bool verbose = true
+ );
+
+ //- Open libraries listed in 'libsEntry' entry in the dictionary,
+ //- warn by default if problems occur
+ dlLibraryTable
+ (
+ const word& libsEntry,
+ const dictionary& dict,
+ bool verbose = true
+ );
+
+ //- Open libraries listed in 'libsEntry' entry in the dictionary,
+ //- warn by default if problems occur
+ dlLibraryTable
+ (
+ const dictionary& dict,
+ const word& libsEntry,
+ bool verbose = true
+ );
//- Destructor. Closes all libraries loaded by the table.
~dlLibraryTable();
+ // Static Member Functions
+
+ //- Library basename without leading 'lib' or trailing '.so'
+ static word basename(const fileName& libPath);
+
+ //- Library fullname, prefix with 'lib', suffix with '.so'
+ // \note the suffix is system-dependent
+ static word fullname(word libName);
+
+ //- Table of global libraries
+ static dlLibraryTable& libs();
+
+ //- Low-level interface to execute global "void funcName(true)"
+ //- from the library, typically for additional loading.
+ // If called, it should be the first step after opening a library.
+ // \return true if the function was found and executed
+ static bool loadHook
+ (
+ void* handle,
+ const std::string& funcName,
+ const bool verbose = false,
+ const std::string& context = "" //!< Calling context for warnings
+ );
+
+ //- Low-level interface to execute global "void funcName(false)"
+ //- from the library, typically for unloading.
+ // If called, it should be the last step before closing a library.
+ // \return true if the function was found and executed
+ static bool unloadHook
+ (
+ void* handle,
+ const std::string& funcName,
+ const bool verbose = false,
+ const std::string& context = "" //!< Calling context for warnings
+ );
+
+
// Member Functions
//- True if there are no libraries loaded by the table
@@ -120,6 +214,9 @@ public:
//- The number of libraries loaded by the table
label size() const;
+ //- Names of the libraries in use
+ List loaded() const;
+
//- Names of the libraries in use, or requested
const UList& names() const
{
@@ -147,21 +244,41 @@ public:
//- These names will normally have been added with the append() method.
bool open(bool verbose = true);
- //- Open the named library, optionally warn if problems occur
+ //- Open the named library, warn by default if problems occur.
+ // An empty name is a silent no-op and always returns nullptr.
+ // \return a pointer to the library opened, or nullptr on failure.
void* open(const fileName& libName, bool verbose = true);
- //- Open the named libraries, optionally warn if problems occur
+ //- Open the named libraries, warn by default if problems occur.
// Ignores duplicate names.
bool open(const UList& libNames, bool verbose = true);
+ //- Open the named libraries, warn by default if problems occur.
+ // Ignores duplicate names.
+ bool open
+ (
+ std::initializer_list libNames,
+ bool verbose = true
+ );
+
//- Close the named library, optionally warn if problems occur
+ // Using an empty name is a no-op and always returns false.
bool close(const fileName& libName, bool verbose = true);
//- Find the handle of the named library
+ // Using an empty name is a no-op and always returns nullptr.
void* findLibrary(const fileName& libName);
- //- Open all libraries listed in the 'libsEntry' entry in the
- //- given dictionary.
+ //- Open libraries listed in the 'libsEntry' entry in the dictionary.
+ bool open
+ (
+ const word& libsEntry,
+ const dictionary& dict,
+ bool verbose = true
+ );
+
+ //- Open libraries listed in the 'libsEntry' entry in the dictionary.
+ // Verbose = true
bool open(const dictionary& dict, const word& libsEntry);
//- Open all libraries listed in the 'libsEntry' entry in the
@@ -172,7 +289,8 @@ public:
(
const dictionary& dict,
const word& libsEntry,
- const TablePtr& tablePtr
+ const TablePtr& tablePtr,
+ bool verbose = true
);
diff --git a/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTableTemplates.C b/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTableTemplates.C
index ff39cebf17..8c558acf8b 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTableTemplates.C
+++ b/src/OpenFOAM/db/dynamicLibrary/dlLibraryTable/dlLibraryTableTemplates.C
@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
- Copyright (C) 2018 OpenCFD Ltd.
+ Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -28,7 +28,6 @@ License
#include "dlLibraryTable.H"
#include "dictionary.H"
-#include "fileNameList.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@@ -37,23 +36,24 @@ bool Foam::dlLibraryTable::open
(
const dictionary& dict,
const word& libsEntry,
- const TablePtr& tablePtr
+ const TablePtr& tablePtr,
+ bool verbose
)
{
- fileNameList libNames;
+ List libNames;
dict.readIfPresent(libsEntry, libNames);
label nOpen = 0;
for (const fileName& libName : libNames)
{
- const label nEntries = (tablePtr ? tablePtr->size() : 0);
+ const label nEntries = (tablePtr ? tablePtr->size() : -1);
- if (dlLibraryTable::open(libName))
+ if (dlLibraryTable::open(libName, verbose))
{
++nOpen;
- if (debug && (!tablePtr || tablePtr->size() <= nEntries))
+ if (debug && tablePtr != nullptr && tablePtr->size() <= nEntries)
{
WarningInFunction
<< "library " << libName
@@ -61,12 +61,6 @@ bool Foam::dlLibraryTable::open
<< nl << endl;
}
}
- else
- {
- WarningInFunction
- << "Could not open library " << libName
- << nl << endl;
- }
}
return nOpen && nOpen == libNames.size();
diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C
index d5bc748266..d2d2098488 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C
+++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C
@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
- Copyright (C) 2016-2019 OpenCFD Ltd.
+ Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -28,6 +28,7 @@ License
#include "dynamicCode.H"
#include "dynamicCodeContext.H"
+#include "dlLibraryTable.H"
#include "argList.H"
#include "stringOps.H"
#include "Fstream.H"
@@ -37,15 +38,6 @@ License
#include "dictionary.H"
#include "foamVersion.H"
-#ifdef __APPLE__
- #define EXT_SO ".dylib"
-#elif defined _WIN32
- #define EXT_SO ".dll"
-#else
- #define EXT_SO ".so"
-#endif
-
-
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::dynamicCode::allowSystemOperations
@@ -103,14 +95,6 @@ void Foam::dynamicCode::checkSecurity
}
-Foam::word Foam::dynamicCode::libraryBaseName(const fileName& libPath)
-{
- word libName(libPath.nameLessExt());
- libName.removeStart("lib"); // Remove leading 'lib' from name
- return libName;
-}
-
-
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::dynamicCode::copyAndFilter
@@ -328,13 +312,13 @@ Foam::fileName Foam::dynamicCode::codeRelPath() const
Foam::fileName Foam::dynamicCode::libPath() const
{
- return codeRoot_/libSubDir_/"lib" + codeName_ + EXT_SO;
+ return codeRoot_/libSubDir_/dlLibraryTable::fullname(codeName_);
}
Foam::fileName Foam::dynamicCode::libRelPath() const
{
- return codeRelPath()/libSubDir_/"lib" + codeName_ + EXT_SO;
+ return codeRelPath()/libSubDir_/dlLibraryTable::fullname(codeName_);
}
@@ -514,16 +498,10 @@ bool Foam::dynamicCode::wmakeLibso() const
// cmd[0] = stringOps::expand("$WM_PROJECT_DIR/wmake/wmake");
// This can take a bit longer, so report that we are starting wmake
+ // Even with details turned off, we want some feedback
- if (Foam::infoDetailLevel > 0)
- {
- Info<< "Invoking wmake libso " << this->codePath().c_str() << endl;
- }
- else
- {
- // Even with details turned off, we want some feedback
- Serr<< "Invoking wmake libso " << this->codePath().c_str() << endl;
- }
+ OSstream& os = (Foam::infoDetailLevel > 0 ? Info : Serr);
+ os << "Invoking wmake libso " << this->codePath().c_str() << endl;
if (Foam::system(cmd) == 0)
{
diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H
index 486ae3ee17..438219b505 100644
--- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H
+++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.H
@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
- Copyright (C) 2019 OpenCFD Ltd.
+ Copyright (C) 2019-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -47,7 +47,7 @@ SourceFiles
namespace Foam
{
-// Forward declarations
+// Forward Declarations
class dynamicCodeContext;
class ISstream;
class OSstream;
@@ -60,10 +60,12 @@ class SHA1Digest;
class dynamicCode
{
public:
+
typedef Tuple2 fileAndContent;
private:
- // Private data
+
+ // Private Data
//- Root for dynamic code compilation
fileName codeRoot_;
@@ -104,7 +106,7 @@ private:
protected:
- // Static data members
+ // Static Data Members
//- Root of the LIB target for Make/files
static const char* const libTargetRoot;
@@ -151,7 +153,7 @@ protected:
public:
- // Static data members
+ // Static Data Members
//- Name of the code template environment variable
// Used to located the codeTemplateName
@@ -170,15 +172,12 @@ public:
//- Check security for creating dynamic code
static void checkSecurity(const char* title, const dictionary&);
- //- Return the library basename without leading 'lib' or trailing '.so'
- static word libraryBaseName(const fileName& libPath);
-
// Constructors
//- Construct for a specified code name and code directory name
// Defaults to using the code name for the code directory name
- dynamicCode
+ explicit dynamicCode
(
const word& codeName,
const word& codeDirName = ""