在库内部使用不透明指针

Using opaque pointers internally in library

编写库时,有时您希望对用户隐藏实现细节。理想的工具是不透明结构或不透明指针。

当库中的另一个源文件希望使用来自该结构的数据时出现问题。例如:这是头文件 apple.h:

typedef struct apple_ Apple;
Apple* new_apple();
void delete_apple(Apple* a);
/* ... */

这是结构体的定义Apple:

typedef struct apple_ {
  int taste; /* the higher the better */
}

通常,这部分位于 apple.c

但是如果 Store 希望根据口味对他们的苹果进行排名怎么办?这可能是 store.c:

#include "apple.h"
void rankApples(Store* store) {
    int t = store->apples[0]->taste; /* unreachable field */
}

一个解决方案可能是复制结构定义(我不想那样)或在 apple.[hc] 中创建一个函数:int taste_apple(Apple* a) { return a->taste; },但我希望用户不要这样做知道苹果有多好吃

如何解决?我应该创建另一个由 apple.cstore.c 使用的头文件吗?如何阻止用户包含该头文件?

你想让店家知道一条信息,但你又不愿意给他们。那只是没有意义。

您可以为两个文件制作 apple 结构 public(这可能意味着将其分开并由两者包含,但不将其提供给用户),或者如您所说,创建一个可以检索苹果味道的函数。

但是,我想说,如果口味仅用于排名目的,为什么不创建一个函数,假设 getPoints 一个 store 可以用来给苹果排名?

int getPoints(Apple* a) {
    return a->taste*2;
}

当向使用客户端隐藏库详细信息时,执行您在上一段中描述的操作并不少见。但是你不需要 "ship the details" 你的 lib 和 public header.

例如:

mylib.h

#ifndef MYLIB_H

typedef struct Data Data;

void Func(Data *data);

#endif

mylibint.h

#ifndef MYLIB_H_INTERNAL
#define MYLIB_H_INTERNAL

struct Data
{
    // implementation goes here
    int value;
};

#endif

mylib.c

#include "mylib.h"
#include "mylibint.h"


Data *GetData()
{
    return calloc(1, sizeof(Data));
}

void FreeData(Data *data)
{
    free(data);
}

void DoSomething(Data * data)
{
    // do something with data
}

在这样做的过程中,您的图书馆将建立,同时消耗两个 header。您需要随附的唯一 header 是 mylib.h。稍后,客户端可以这样做:

client.c

#include "mylib.h"

int main()
{
    Data *data = GetData();
    DoSomething(data);
    FreeData(data);
}

他们幸福地不知道 Data 除了一些不透明的类型之外还有什么。