c - 使用结构指针和 C 接口的“正确”方法是什么?
问题描述
我正在尝试设置一个系统,在其中传递指向结构的指针,同时向最终用户隐藏结构的定义。我有两个似乎可行的选择,但我不知道我是否让这件事变得比需要的更难,错过了权衡,或者只是做一些非常愚蠢的事情。对于任何方法,我都坚持使用 C,不能使用 C++。此外,这最终将需要通过 Fortran 程序进行对话,我正在努力使其尽可能简单。
我有一个小工具来演示这个概念。选项一使用指向指针的 void 指针,以便我可以在必要时从函数返回一个状态整数。但是,我不喜欢在通话之前进行 malloc,因为我担心 Fortran 方面的事情。这可能是没有根据的,因为我还没有做过那个演示。选项二只是从函数返回一个 void 指针,但我失去了以这种方式返回状态的能力。对于这两个版本,我确实有一个自定义的免费功能,即使不一定使用确切的当前实现。该结构有它自己的 void 指针,它将根据选项输入进行定义,并且它需要在拆卸过程中释放它。
#include <stdio.h>
#include <stdlib.h>
struct State
{
int type;
void *data;
};
int Init1(int option, void **state);
void* Init2(int option);
void printState(void *state);
void free1(void **state);
void free2(void *state);
void* allocateData(int option);
int main(int argc, char *argv[])
{
void **ps1;
void *s2;
int ret;
ps1 = malloc(sizeof(void*));
ret = Init1(1, ps1);
printState(*ps1);
free1(ps1);
s2 = Init2(2);
printState(s2);
free2(s2);
return 0;
}
int Init1(int option, void **state)
{
(*state) = malloc(sizeof(struct State));
struct State* ret = *state;
ret->type = option;
return 0;
}
void free1(void **state)
{
free(*state);
free(state);
}
void* Init2(int option)
{
struct State* ret = malloc(sizeof(struct State));
ret->type = option;
return ret;
}
void free2(void *state)
{
free(state);
}
void printState(void *state)
{
struct State* data = state;
printf("Type : %d\n", data->type);
}
解决方案
以FILE
输入stdio.h
为例。您可以公开类型名称而不公开其定义:
/**
* State.h
*/
#ifndef STATE_H
#define STATE_H
/**
* Create a typedef name for the *incomplete* type "struct State"
*/
typedef struct State STATE;
/**
* Define your interface
*/
void Init1( int, STATE ** );
STATE *Init2( int );
void printState( STATE * );
void sFree( STATE * );
void sFree2( STATE ** );
#endif
然后在实现文件中完成类型的定义:
/**
* State.c
*/
#include "State.h"
#include <stdlib.h>
...
/**
* Complete the type definition
*/
struct State {
int type;
void *data;
};
/**
* Implement the interface
*/
int Init1( int option, STATE **s )
{
*s = malloc ( sizeof **s ); // type definition is complete at this
if ( *s ) // point so we can use sizeof
{
(*s)->type = option;
}
return *s != NULL; // I'm *assuming* you want to return true (1)
} // if the allocation is successful
...
现在,当谈到与 Fortran 的互操作时……我帮不上什么忙。我在 30 多年前的 VAX 上做过一次,它不涉及像这样的不透明类型。
推荐阅读
- database - 如何在 Flutter Floor 中实际查看数据库?
- python - 如何在 Pyspark 中过滤数据框
- python - 需要一个有效的算法来根据规格移动游戏块(游戏:Janggi)
- flutter - 颤振 2.0.1 发布失败
- angular - 令牌服务,令牌拦截器帮助,令牌未存储,Angular 10
- javascript - 有没有办法使反应语义ui中的动画平滑?
- razor - 如何在 Blazor Webassembly 中完全禁用组件
- python - re 和 TypeError 的问题:预期的字符串或类似字节的对象
- angular - 在 onLazyLoad 事件中设置排序会触发 p-table 上的无限循环
- html - 文本框大小更改时光标位置更改