在库内部使用不透明指针
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.c
和 store.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
除了一些不透明的类型之外还有什么。
编写库时,有时您希望对用户隐藏实现细节。理想的工具是不透明结构或不透明指针。
当库中的另一个源文件希望使用来自该结构的数据时出现问题。例如:这是头文件 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.c
和 store.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
除了一些不透明的类型之外还有什么。