加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – C API函数的样式

发布时间:2020-12-16 03:25:05 所属栏目:百科 来源:网络整理
导读:我正在开发一个支持多种编程环境的库,如VB6和FoxPro.我必须坚持C约定,因为它是最低的共同点.现在我对这个风格有疑问. 假设函数进程输入并返回一个字符串.在此过程中,可能会发生错误.目前提出的风格是这样的: int func(input params... char* buffer,unsigne
我正在开发一个支持多种编程环境的库,如VB6和FoxPro.我必须坚持C约定,因为它是最低的共同点.现在我对这个风格有疑问.

假设函数进程输入并返回一个字符串.在此过程中,可能会发生错误.目前提出的风格是这样的:

int func(input params... char* buffer,unsigned int* buffer_size);

这种风格的好处是原型中包含了所有内容,包括错误代码.并且可以避免内存分配.问题是该功能非常冗长.并且因为buffer_size可以是任何,所以需要更多的代码来实现.

另一种选择是返回char *,并返回NULL以指示错误:

char* func(input params...);

此样式需要调用者删除缓冲区.内存分配是必需的,因此服务器程序可能会面临内存碎片问题.

第二个选项的变体是使用线程局部变量来保存返回的指针char *,这样用户就不需要删除缓冲区.

你喜欢哪种风格?还有原因吗?

解决方法

谈到这个问题,我有点“受损的商品”.我曾经为嵌入式电信设计和维护相当大的API.您不能将任何事情视为理所当然的环境.甚至不是全局变量或TLS.有时甚至堆缓冲区显示实际上是寻址ROM内存.

因此,如果您正在寻找“最低公分母”,您可能还想考虑目标环境中可用的语言结构(编译器可能接受标准C中的任何内容,但如果某些内容不受支持,则链接器会说不.

话虽如此,我总是会选择替代方案1.部分原因是(正如其他人所指出的那样),您不应该直接为用户分配内存(间接方法将进一步解释).即使用户保证使用纯C和纯C,他们仍然可以使用他们自己的自定义内存管理API来跟踪泄漏,诊断日志记录等.通常赞赏支持这样的策略.

在处理API时,错误通信是最重要的事情之一.由于用户可能有不同的方法来处理代码中的错误,因此您应该尽可能地保持整个API中的通信.用户应该能够以一致的方式和最少的代码将错误处理包装到您的API中.我通常总是建议使用清晰的枚举代码或定义/ typedef.我个人更喜欢typedef:ed enums:

typedef enum {

  RESULT_ONE,RESULT_TWO

} RESULT;

因为它提供了类型/分配安全性.

具有get-last-error函数也很不错(但需要集中存储),我个人仅将其用于提供有关已识别错误的额外信息.

替代方案1的详细程度可以通过制作这样的简单化合物来限制:

struct Buffer
{
  unsigned long size;
  char* data;
};

然后你的api可能看起来更好:

ERROR_CODE func( params...,Buffer* outBuffer );

这一战略也为更精细的机制开辟了道路.比如说你必须能够为用户分配内存(例如,如果你需要调整缓冲区的大小),那么你可以提供一个间接的方法:

struct Buffer
{
  unsigned long size;
  char* data;
  void* (*allocator_callback)( unsigned long size );
  void  (*free_callback)( void* p );
};

当然,这种结构的风格总是可以进行严肃的辩论.

祝好运!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读