dlinfo (… SERPATH…) Оболочка C ++

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]);
    }
};
}


0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *