diff --git a/cpp/src/arrow/util/io_util.cc b/cpp/src/arrow/util/io_util.cc index 1ed28d717d3..7c6bca20814 100644 --- a/cpp/src/arrow/util/io_util.cc +++ b/cpp/src/arrow/util/io_util.cc @@ -2278,4 +2278,24 @@ Result GetSymbol(void* handle, const char* name) { #endif } +Status CloseDynamicLibrary(void* handle) { + if (handle == nullptr) { + return Status::Invalid("Attempting to close null library handle"); + } +#ifdef _WIN32 + if (FreeLibrary(reinterpret_cast(handle))) { + return Status::OK(); + } + // win32 api doc: "If the function fails, the return value is zero." + return IOErrorFromWinError(GetLastError(), "FreeLibrary() failed"); +#else + if (dlclose(handle) == 0) { + return Status::OK(); + } + // dlclose(3) man page: "On success, dlclose() returns 0; on error, it returns a nonzero value." + auto* error = dlerror(); + return Status::IOError("dlclose() failed: ", error ? error : "unknown error"); +#endif +} + } // namespace arrow::internal diff --git a/cpp/src/arrow/util/io_util.h b/cpp/src/arrow/util/io_util.h index 892641d4bc5..07d31854e4e 100644 --- a/cpp/src/arrow/util/io_util.h +++ b/cpp/src/arrow/util/io_util.h @@ -443,6 +443,13 @@ ARROW_EXPORT Result LoadDynamicLibrary(const char* path); /// returned; instead an error will be raised. ARROW_EXPORT Result GetSymbol(void* handle, const char* name); +/// \brief Close a dynamic library +/// +/// This wraps dlclose() except on Windows, where FreeLibrary() is called. +/// +/// \return Status::OK() if the library was closed successfully, otherwise an error is returned. +ARROW_EXPORT Status CloseDynamicLibrary(void* handle); + template Result GetSymbolAs(void* handle, const char* name) { ARROW_ASSIGN_OR_RAISE(void* sym, GetSymbol(handle, name));