在推出自己的结构时提供辅助功能 [英] Providing helper functions when rolling out own structures

查看:28
本文介绍了在推出自己的结构时提供辅助功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我正在开发一个 C 共享库并且我有自己的结构.为了使库使用者更容易对这些结构实例进行常见操作,我可以在结构本身内部提供指向此类函数的函数指针吗?这是一个好习惯吗?在使用不同的参数并行调用实用程序函数等情况下,多线程会存在问题吗?

if I am developing a C shared library and I have my own structs. To make common operations on these struct instances easier for library consumers, can I provide function pointers to such functions inside the struct itself? Is it a good practice? Would there be issues with respect to multithreading where a utility function is called in parallel with different arguments and so on?

我知道它更接近 C++ 类,但我希望坚持使用 C 并学习如何使用过程语言而不是 OOP 来完成它.

I know it goes a lot closer to C++ classes but I wish to stick to C and learn how it would be done in a procedural language as opposed to OOP.

举个例子

typedef struct tag tag;
typedef struct my_custom_struct my_custom_struct;

struct tag
{
    // ...
};

struct my_custom_struct
{
    tag *tags;
    my_custom_struct* (*add_tag)(my_custom_struct* str, tag *tag);  
};

my_custom_struct* add_tag(my_custom_struct* str, tag *tag)
{
    // ...
}

其中 add_tag 是一个帮助器,它设法将标签添加到 *str 内的标签列表中.我在 libjson-c 中看到了这种模式,就像这里 - http://json-c.github.io/json-c/json-c-0.13.1/doc/html/structarray__list.html.array_list 里面有一个函数指针来帮助释放它.

where add_tag is a helper that manages to add the tag to tag list inside *str. I saw this pattern in libjson-c like here- http://json-c.github.io/json-c/json-c-0.13.1/doc/html/structarray__list.html. There is a function pointer given inside array_list to help free it.

推荐答案

为了使库更容易对这些结构体实例进行常见操作消费者,我可以提供指向内部这些函数的函数指针吗结构本身?

To make common operations on these struct instances easier for library consumers, can I provide function pointers to such functions inside the struct itself?

可以为您的结构赋予函数指针成员,指向其参数包括指向您的结构类型的指针的函数类型,并且旨在或多或少地像 C++ 实例方法一样使用,或多或少如所示在问题中.

It is possible to endow your structures with members that are function pointers, pointing to function types whose parameters include pointers to your structure type, and that are intended to be used more or less like C++ instance methods, more or less as presented in the question.

这是一个好习惯吗?

TL;DR:没有.

您将遇到的第一个问题是正确初始化这些指针成员.尽管名称对应,但结构实例中的函数指针不会自动初始化为指向特定函数.除非您使结构类型不透明,否则用户可以(并且毫无疑问有时)声明实例而无需调用您为此目的提供的任何构造函数模拟函数,然后就会出现混乱.

The first problem you will run into is getting those pointer members initialized appropriately. Name correspondence notwithstanding, the function pointers in instances of your structure will not automatically be initialized to point to a particular function. Unless you make the structure type opaque, users can (and undoubtedly sometimes will) declare instances without calling whatever constructor-analog function you provide for the purpose, and then chaos will ensue.

如果您确实使结构不透明(这毕竟不是一个坏主意),那么无论如何您都需要非成员函数,因为您的用户将无法直接访问函数指针.也许是这样的:

If you do make the structure opaque (which after all isn't a bad idea), then you'll need non-member functions anyway, because your users won't be able to access the function pointers directly. Perhaps something like this:

struct my_custom_struct *my_add_tag(struct my_custom_struct *str, tag *tag) {
    return str->add_tag(str, tag);
}

但是如果您要提供这些,那么额外的间接级别有什么意义呢?(答案:唯一很好的理由是在不同的情况下,函数指针可以指向不同的函数.)

But if you're going to provide for that, then what's the point of the extra level of indirection? (Answer: the only good reason for that would be that in different instances, the function pointer can point to different functions.)

如果您不使结构不透明,则类似.那么你可能会假设用户会(更多)直接调用

And similar applies if you don't make the structure opaque. Then you might suppose that users would (more) directly call

str->add_tag(str, tag);

但究竟是什么让这变得简单

but what exactly makes that a convenience with respect to simply

add_tag(str, tag);

?

所以总的来说,不,我不认为这种方法一般来说是一种好的做法.在有限的情况下,按照这些方式做一些事情可能是有意义的,但不是一般的图书馆惯例.

So overall, no, I would not consider this approach a good practice in general. There are limited circumstances where it may make sense to do something along these lines, but not as a general library convention.

会不会有问题关于在其中调用实用程序函数的多线程平行于不同的论点等等?

Would there be issues with respect to multithreading where a utility function is called in parallel with different arguments and so on?

不会比以任何其他方式指定的函数更是如此,除非函数指针本身被修改.

Not more so than with functions designated any other way, except if the function pointers themselves are being modified.

我知道它更接近 C++ 类,但我希望坚持使用 C并学习如何用程序语言而不是面向对象.

I know it goes a lot closer to C++ classes but I wish to stick to C and learn how it would be done in a procedural language as opposed to OOP.

如果你想学习 C 的习语和约定,那么一定要这样做.你所描述的不是一个.C 代码和库绝对可以使用封装等面向对象原则进行设计,在某种程度上甚至可以使用多态性,但通常无法通过您描述的机制实现.这个答案涉及用于此目的的一些方法.

If you want to learn C idioms and conventions then by all means do so. What you are describing is not one. C code and libraries can absolutely be designed with use of OO principles such as encapsulation, and to some extent even polymorphism, but it is not conventionally achieved via the mechanism you describe. This answer touches on some of the approaches that are used for the purpose.

这篇关于在推出自己的结构时提供辅助功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆