2014-01-21 65 views
7

我想做一些看起来不可能的事情。是否可以隐藏标准头部的一部分(C)?

我想写3个文件:main.c中了foo.hfoo.c的
的想法是在foo.h中foo.c的以这样的方式,它的成员是在main.c中可见定义结构。其中一个结构成员的类型为FILE,如标准标头<stdio.h>中所定义。但<stdio.h>的功能和宏必须在文件main.c内不可见。

该解决方案必须符合标准C(C99和/或C11)和便携式。 这可能吗?

foo.h中被包含(#include)在两个,main.c中foo.c的
标准标头<stdio.h>#仅包含在foo.c中,但不包含在main.c中。

我要声明一个struct如下:

struct myfile_s { 
    FILE *F; 
    char *filename; 
    char buff[100]; 
} myfile; 

对于接下来,只有成员FILE *F是很重要的。
结构myfile将通过出现在foo.c中的函数进行初始化和修改。
这样做的目的是做在foo.h中,这反过来又在foo.c的被定义声明myfile通过extern功能的文件操作。

文件操作涉及标准功能<stdio.h>,但这些功能必须隐藏在文件main.c中。 但是,我想直接从main.c访问myfile的成员。 这意味着struct myfile_s的定义必须在foo.h中完成(也就是说,它不能被使用不完整结构声明的技巧“延迟”,如struct myfile_s ;)。

总之,我希望该类型FILEmain.c中和/或foo.h中是可见的,但<stdio.h>声明其余一直隐藏了他们。

另一个限制:直接复制“手头上”提供的FILE的定义不可取,因为代码必须是可移植的。

我的第一次尝试是通过将其写入foo.c来隐藏struct myfile
该代码是:

foo.h中

struct myfile_s; 

struct myfile_s myfile; 

extern void startfile(struct myfile *f); 

的foo.c

#include <stdio.h> 
#include "foo.h" 

struct myfile_s { 
    FILE *F; 
    char *filename; 
    char buff[100]; 
} myfile; 

void startfile(struct myfile *f) 
{ 
    // Do some stuff... 
} 

的main.c

#include "foo.h" 

int main(void) 
{ 
    myfile.F = NULL; // This kind of access bring error, but I want to do it anyway!! 
    startfile(&myfile); 
    return 0; 
} 

延迟struct myfile_s声明避免了需要包括<stdio.h>foo.h中,所以头工作正常,但结构类型仍然不完整,所以获得myfile.F不能main.c中来完成。

因此:如何访问myfile.F?

我尝试另一种方式,当然,给出了错误太:

foo.h中

struct myfile_s { 
    FILE *F; 
    char *filename; 
    char buff[100]; 
} myfile; 

extern void startfile(struct myfile *f); 

foo.c的

#include <stdio.h> 
#include "foo.h" 

void startfile(struct myfile *f) 
{ 
    // Do some stuff... 
} 
+0

对于使用两个不同的头文件是不是足够了?一个内部的头文件和一个外部?外部只知道void指针(或者在你的情况下是结构的FILE指针部分),而在内部你将这些void指针指向你的类型,所以具有内部头文件的指针知道你想保持内部的部分,并且外部头部jsut显示你想要发表什么。 – dhein

+0

您是否曾尝试在'foo.h'中包含'',即您在哪里定义您的结构体......我更愿意在标题中声明 –

+0

什么不适用于第二种方法?它看起来大部分在正确的轨道上。 –

回答

7
struct myfile_s { 
    void *pPrivateThings; // This could be the FILE* or another private structure 
    char *filename; 
    char buff[100]; 
} myfile; 

我将分配另一个pri vate结构上创建:

struct myprivatefile_s { 
    FILE *F; 
    // You could add other fields here that are not public 
} myprivatefile; 

myprivatefile *privateThings = malloc(sizeof(myprivatefile)); 
myfile.pPrivateThings = privateThings; 
privateThings->F = fopen(); 

这样,你可以继续添加不需要可见的东西(即,私人)到你心中的内容。

+1

看起来像pimpl C++习语。只是,我想添加你可以声明'struct myprivatefile_s;'而不在“public”头文件中定义它,并且在指针中使用类型而不是void *'。 – Medinoc

+0

您正在使用'myfile'作为“类型”,但它是'struct myfile_s'类型的变量。但这是一个小错误。我试过使用void *指针,它可以访问myfile.F,但现在问题是“实际”类型的“FILE”不是“纯”(它不是真正的)。但是,基于我执行问题的方式,您已经给出了很好的答案。这不是我所期待的,但你的回答是我最喜欢的,因为你给了我几个想法。 – pablo1977

+0

感谢您指出错误。已经纠正它,并显示如何使用它的文件指针。 – noelicus

6

这一切都是不必要的复杂,不是吗?

看起来好像你真的不知道你想要什么。为什么要在foo.h中有一个myfile的实例?为什么要在main中明确设置myfile.F?为什么不写myfile_init这样的函数,在foo.c中有这个功能,它有完整的访问权限?

我会做一个不透明的结构的一个typedef在foo.h,在foo.h定义的东西,实现构造函数和访问函数,然后创建一个main.cmyfile实例:

foo.h中

typedef struct Myfile Myfile; 

Myfile *myfile_open(const char *filename); 
myfile_process(Myfile *f, ...); 
int myfile_close(Myfile *f); 

foo。ç

#include <stdio.h> 

struct Myfile { 
    FILE *f; 
    ... 
}; 

// implement myfile_xxx functions 

的main.c

#include "foo.h" 

int main() 
{ 
    Myfile *f = myfile_open("rhubarb.txt"); 

    if (f == NULL) exit(1); 
    myfile_process(f, ...); 
    myfile_close(f); 

    return 0; 
} 

无需部分包括其他头。通过将初始化移动到myfile_open,所有内容都整齐地封装在foo.c中。主程序只能看到句柄。非常喜欢标准FILE *手柄,真的。