这个问题在这里已有答案:
我想隐藏库用户的内部类型。 目前我有这样的事情:
foo.h中
typedef struct public
{
uint16 a;
//...
unsigned char internals[4];
} public_type;
foo.c的
typedef struct public
{
uint32_t a;
}internals_type;
然后在函数中,我正在做一个类似的演员。
void bar(public_type * const public_struct)
{
internals_type* const internals = &public_struct->internals;
intrnals->a = getSomething();
// .....
}
有没有更好的方法呢?
我已经尝试了一些奇怪的东西与标题中的联合和指针,但没有什么似乎更好,我很好奇,如果这可以得到更清洁或至少如果从一种类型指针指向另一种指针的警告可以被删除。
我建议你阅读更多关于opaque data types的内容,并考虑一下FILE
结构。
简而言之,不要将您的结构分为“公共”和“私有”变体(这种方式是疯狂和可能的未定义行为)。相反,只需在公共头文件中声明一个结构,并让您的函数返回指向该结构的指针或接受指向该结构的指针的参数。
然后在库中内部有一个私有头文件,它具有结构的定义,并使用该头文件进行实现。
#ifndef PUBLIC_HEADER_FILE_H
#define PUBLIC_HEADER_FILE_H
typedef my_private_structure MY_PUBLIC_TYPE;
MY_PUBLIC_TYPE *mylib_create(void);
void mylib_destroy(MY_PUBLIC_TYPE *ptr);
#endif
#ifndef PRIVATE_HEADER_FILE_H
#define PRIVATE_HEADER_FILE_H
#include "public_header_file.h"
struct my_private_structure
{
// Some private fields here
};
#endif
#include "private_header_file.h"
#include <stdlib.h>
MY_PUBLIC_TYPE *mylib_create(void)
{
MY_PUBLIC_TYPE *ptr = malloc(sizeof *ptr);
return ptr;
}
void mylib_destroy(MY_PUBLIC_TYPE *ptr)
{
free(ptr);
}
您将public_header_file.h
与您的图书馆一起分发。它是库用户将使用的头文件。
您的库的源代码,尤其是private_header_file.h
文件不应该分发,或者如果您创建一个开源库,则至少不会安装。
请注意,此方案使所有结构都“私有”,这通常是一个好主意,因为您可以根据需要修改它,而无需库的用户需要使用您的库重建其应用程序。要访问私有结构的成员,您可以使用只返回需要访问的成员的值的函数。
通常,您使用void*
隐藏您的实现,例如
void *create_foo(int param1, int param2);
void print_foo(void* foo);
int operate_on_foo(void* foo);
因此,您将函数中的void*
“强制转换”为内部类型。
这样做的缺点是,编译器无法帮助您处理类型,例如:库的用户可以使用int*
并将其传递给您的函数,编译器将接受它。当您使用实际类型时,编译器会抱怨。
你可以在foo.h做:
typedef struct internals_type;
typedef struct {
uint16 a;
internals_type* internals;
} public_type
包含foo.h就足以让你的用户编译,而不知道internals_type
里面到底是什么。