是否可以隐藏标准标题的一部分(在C中)?

pab*_*977 7 c

我想做一些看似不可能的事情.

我想写3个文件:main.c,foo.h,foo.c.
我们的想法是在foo.hfoo.c中定义一个结构,使其成员在main.c中可见.其中一个struct成员具有FILE标准头中定义的类型<stdio.h>.但是<stdio.h>必须在main.c文件中保持不可见的函数和宏.

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

标题foo.hmain.cfoo.c中都是#included .
标准头文件<stdio.h>仅在foo.c中包含#included ,但在main.c中不包含.

我想声明struct如下:

struct myfile_s {
   FILE *F;
   char *filename;
   char buff[100];
} myfile;
Run Code Online (Sandbox Code Playgroud)

对于以下内容,只有成员FILE *F才是重要的.
结构myfile将由foo.c中出现的函数初始化和修改.
目的是myfile通过foo.h中extern声明的函数对文件进行操作,而foo.h中的函数又必须在foo.c中定义.

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

简而言之,我希望类型FILEmain.c和/或foo.h中可见,但其余的<stdio.h>声明对它们保持隐藏.

另一个限制:直接复制"手头" FILE提供的定义的想法<stdio.h>是不可取的,因为代码必须是可移植的.

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

foo.h中

struct myfile_s;

struct myfile_s myfile;

extern void startfile(struct myfile *f);
Run Code Online (Sandbox Code Playgroud)

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...
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

延迟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);
Run Code Online (Sandbox Code Playgroud)

foo.c的

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

void startfile(struct myfile *f) 
{
    // Do some stuff...
}
Run Code Online (Sandbox Code Playgroud)

noe*_*cus 7

struct myfile_s {
   void *pPrivateThings; // This could be the FILE* or another private structure
   char *filename;
   char buff[100];
} myfile;
Run Code Online (Sandbox Code Playgroud)

我会在创建时分配另一个私有结构:

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(); 
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以继续添加不需要对您的内容可见(即私有)的内容.


M O*_*ehm 6

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

看起来好像你真的不知道自己想要什么.为什么你想拥有的单个实例myfilefoo.h?你为什么要myfile.F明确设置main?为什么不写像一个功能myfile_init对于在foo.c,它具有完全访问权限?

我会做一个opaque结构的typedef foo.h,定义东西并实现构造函数和访问器函数foo.h,然后创建一个myfilein 的实例main.c:

foo.h中

typedef struct Myfile Myfile;

Myfile *myfile_open(const char *filename);
myfile_process(Myfile *f, ...);
int myfile_close(Myfile *f);
Run Code Online (Sandbox Code Playgroud)

foo.c的

#include <stdio.h>

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

// implement myfile_xxx functions
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

无需部分包含其他标头.通过移动初始化myfile_open,一切都被巧妙地封装在其中foo.c.主程序只看到句柄.FILE *真的像标准手柄一样.