我想向库用户隐藏内部类型。
目前我有这样的东西:
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();
// .....
}
是否有更好的方法?
我已经尝试了一些奇怪的东西,在标头中使用了联合和指针,但是似乎没有什么更好的了,我很好奇这是否可以变得更干净,或者至少是警告将指针从一种类型转换为指针到另一个可以被删除。
答案 0 :(得分:18)
我建议您阅读有关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
文件,应该不分发,或者,如果您制作了开源库,则至少不安装。
请注意,此方案使结构的所有内容都成为“私有”,这通常是一个好主意,因为这样您就可以根据需要进行修改,而无需库的用户使用以下方法重建应用程序您的图书馆。要访问私有结构的成员,您可以使用仅返回需要访问的任何成员的值的函数。
答案 1 :(得分:4)
通常,您使用void*
隐藏实现,例如
void *create_foo(int param1, int param2);
void print_foo(void* foo);
int operate_on_foo(void* foo);
因此您将函数中的void*
“投射”到内部类型。
缺点是,编译器无法帮助您选择类型,例如库的用户可以使用int*
并将其传递给您的函数,编译器将接受它。当您使用实际类型时,编译器会抱怨。
答案 2 :(得分:2)
您可以在foo.h中进行操作:
INNER JOIN
包含foo.h就足以让您的用户编译,而无需知道MySQL
的确切内部内容。