首页 > 解决方案 > API 设计困境:不透明的句柄

问题描述

我正在设计一个库,该库试图在单个通用句柄 (1) 或其一组 (2) 下统一平台特定细节。

为了使问题更具体,我将提供两个实现的摘录和一个示例用法。

(1) 标记工会;包罗万象的类型:

enum tb_handle_kind {};

/* These two are never exposed to the user: */
struct tb_dir {
    struct _WIN32_FIND_DATAW find_data;
    HANDLE search_handle;
};

struct tb_file {
    HANDLE native_handle;
};

struct tb_handle {
    enum tb_handle_kind kind;

    union {
        struct tb_file file;
        struct tb_dir dir;
    };
};

您将通过以下方式使用它:

file_open(struct tb_handle *, const char *);
handle_close(struct tb_handle *);

struct tb_handle file;
file_open(&file, "path/to/file");

...

handle_close(&file); /* No need for a cast, or a file-specfic function. */

(2) 通用句柄作为其他人的基类:

struct tb_handle {
    /* Fields shared by each handle. */
};

struct tb_dir {
    struct tb_handle base; /* Now a "base class" of tb_dir. */
    struct _WIN32_FIND_DATAW find_data;
    HANDLE search_handle;
};

用法:

/* Either a pair of init/close functions. */
int dir_open(struct tb_dir *, const char *);
int dir_close(struct tb_dir *);

/* Or handle_close from the previous example, that now requires a cast: */
handle_close((struct tb_handle *) &some_dir);

据我所知,(1) 以牺牲类型安全为代价提供了一个更易于使用的 API,而 (2) 提供了更多的心理体操,并提高了安全性(您不能将错误类型的句柄传递给函数)。

从用户的角度来看,您更愿意使用哪一个?

标签: capi-design

解决方案


推荐阅读