dlfcn.h представляет собой библиотеку функций C для работы с динамическими зависимостями (разделяемыми объектами). Я экспериментировал с их оберткой в C ++ API, в основном как практика создания оболочки для C ++.
Это отрывок из моего процесса упаковки Dl_serinfo части dlinfo(...) в библиотеке C. Для справки:
typedef struct { size_t dls_size; /* Size in bytes of the whole buffer */ unsigned int dls_cnt; /* Number of elements in 'dls_serpath' */ Dl_serpath dls_serpath[1]; /* Actually longer, 'dls_cnt' elements */ } Dl_serinfo;
И Dl_serpath:
typedef struct { char *dls_name; /* Name of library search path directory */ unsigned int dls_flags; /* Indicates where this directory came from */ } Dl_serpath;
Обратите внимание, что dls_serpath член Dl_serinfo является «гибким элементом массива», и весь Dl_serinfo структура должна быть выделена с достаточным пространством для dls_cnt записи в массиве.
Моя обертка:
#include <dlfcn.h>
#include <cstddef>
#include <memory>
#include <stdexcept>
#include <string_view>
namespace dl {
class dl_error : public std::runtime_error {
public:
using std::runtime_error::runtime_error;
};
class serinfo;
class serpath {
friend class serinfo;
private:
std::string_view name_;
unsigned int flags_;
explicit serpath(::Dl_serpath path)
: name_(path.dls_name)
, flags_(path.dls_flags)
{}
public:
std::string_view name() const { return name_; }
unsigned int flags() const { return flags_; }
};
class serinfo {
private:
std::unique_ptr<std::byte[]> bytes;
public:
explicit serinfo(void* dlhandle) {
::Dl_serinfo size;
if (::dlinfo(dlhandle, RTLD_DI_SERINFOSIZE, &size)) {
throw dl_error(::dlerror());
}
bytes = std::make_unique<std::byte[]>(size.dls_size);
if (::dlinfo(dlhandle, RTLD_DI_SERINFOSIZE, bytes.get())) {
throw dl_error(::dlerror());
}
if (::dlinfo(dlhandle, RTLD_DI_SERINFO, bytes.get())) {
throw dl_error(::dlerror());
}
}
unsigned int cnt() const {
return reinterpret_cast<::Dl_serinfo const*>(bytes.get())->dls_cnt;
}
dl::serpath serpath(unsigned int index) const {
return dl::serpath(
reinterpret_cast<::Dl_serinfo const*>(bytes.get())->dls_serpath[index]);
}
};
}
