微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – C API函数的样式

我正在开发一个支持多种编程环境的库,如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 );
};

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

祝好运!

原文地址:https://www.jb51.cc/c/111524.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐