C 如何使用宏或其他机制强制API定义?

C 如何使用宏或其他机制强制API定义?,c,api,macros,c-preprocessor,C,Api,Macros,C Preprocessor,我有一个C头文件作为我正在开发的API的一部分,它公开了许多函数。例如: api.h void foo(); int bar(char * foobar); 现在,我公开的大多数函数实际上都是在API中定义的,但是,有些函数我留给使用它的开发人员自己实现。为了使开发人员更容易操作并强制遵守我的API,我添加了以下宏: api.h(修改) 按如下方式使用: 实现.c #include "api.h" DEFINE_FOO() { // Codez } DEFINE_BAR() {

我有一个C头文件作为我正在开发的API的一部分,它公开了许多函数。例如:

api.h

void foo();
int bar(char * foobar);
现在,我公开的大多数函数实际上都是在API中定义的,但是,有些函数我留给使用它的开发人员自己实现。为了使开发人员更容易操作并强制遵守我的API,我添加了以下宏:

api.h(修改)

按如下方式使用:

实现.c

#include "api.h"
DEFINE_FOO() {
    // Codez
}

DEFINE_BAR() {
    // More codez
}

这种方法让我感到困扰的一点是,开发人员将使用DEFINE_*宏,但不一定直觉地认为函数,即“bar”接受参数。有没有改进这种方法的方法,或者有没有更好的方法在C中强制执行自定义API定义?谢谢

我并不真的推荐你的方法,但从技术上讲,你可以让它起作用

可以将参数按如下方式传递到宏:

#define DEFINE_BAR(arg) \
        int bar(char* arg)
现在程序员可以调用

DEFINE_BAR(arg_name) {
    return strlen(arg_name);
}
这将由cpp转化为以下内容:

int bar(char* arg_name) {
    return strlen(arg_name);
}

我不会真的推荐你的方法,但你可以从技术上让它起作用

可以将参数按如下方式传递到宏:

#define DEFINE_BAR(arg) \
        int bar(char* arg)
现在程序员可以调用

DEFINE_BAR(arg_name) {
    return strlen(arg_name);
}
这将由cpp转化为以下内容:

int bar(char* arg_name) {
    return strlen(arg_name);
}

实际上没有必要使用宏,我建议不要使用宏(在过去的35年中,我用宏做了很多“疯狂”的事情)

如果您正在定义API,这意味着您正在为所有函数将[ANSI]原型放入
API.h
。这并不意味着您将实现它们——它只意味着您定义了体系结构/API。任何在
api.h
中没有原型的函数[显然]都不是api的一部分

如果这样做,编译器将标记任何不匹配。只需要求开发人员在顶部包含
api.h

下面是一个
api.h

void foo(void);
int bar(char *foobar);
符合要求的
.c
将干净地编译:

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

void
foo(void)
{
}

int
bar(char *str)
{
    return 0;
}
您将得到编译错误:

bad.c:5:1: error: conflicting types for ‘foo’
 foo(int x)
 ^
In file included from bad.c:1:0:
api.h:2:6: note: previous declaration of ‘foo’ was here
 void foo(void);
      ^

因此,如果开发人员犯了错误,普通的代码定义会处理它。

真的没有必要使用宏,我建议不要使用宏(在过去的35多年中,我用宏做了很多“疯狂”的事情)

如果您正在定义API,这意味着您正在为所有函数将[ANSI]原型放入
API.h
。这并不意味着您将实现它们——它只意味着您定义了体系结构/API。任何在
api.h
中没有原型的函数[显然]都不是api的一部分

如果这样做,编译器将标记任何不匹配。只需要求开发人员在顶部包含
api.h

下面是一个
api.h

void foo(void);
int bar(char *foobar);
符合要求的
.c
将干净地编译:

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

void
foo(void)
{
}

int
bar(char *str)
{
    return 0;
}
您将得到编译错误:

bad.c:5:1: error: conflicting types for ‘foo’
 foo(int x)
 ^
In file included from bad.c:1:0:
api.h:2:6: note: previous declaration of ‘foo’ was here
 void foo(void);
      ^

因此,如果开发人员犯了错误,普通的代码定义将处理它。

使用正确的原型。不推荐使用旧式声明器。堆栈溢出不是讨论的地方。(但我认为您的方法使调试变得更加困难,并且没有增加任何好处)。现在它不使用IDE,但我的经验是,使用宏实现代码会使跟踪源代码变得困难,例如行号不起作用。我建议使用代码宏,不要让生活变得简单,而是在没有其他方法的情况下。对于
qsort
,我认为用户提供的函数
cmp
没有任何问题。我建议不要这样做。如果用户应该提供一些功能,请在文档中进行解释,并在文档中显示所需的签名。宏根本帮不了他,只是让代码看起来不寻常。使用正确的原型。不推荐使用旧式声明器。堆栈溢出不是讨论的地方。(但我认为您的方法使调试变得更加困难,并且没有增加任何好处)。现在它不使用IDE,但我的经验是,使用宏实现代码会使跟踪源代码变得困难,例如行号不起作用。我建议使用代码宏,不要让生活变得简单,而是在没有其他方法的情况下。对于
qsort
,我认为用户提供的函数
cmp
没有任何问题。我建议不要这样做。如果用户应该提供一些功能,请在文档中进行解释,并在文档中显示所需的签名。宏对他没有任何帮助,只是让代码看起来与众不同。你会推荐一个更好的方法或描述它的链接吗?Thanks@pragmatic-penguin更好的方法只是记录用户必须实现的内容。定义第一行的宏对他一点帮助都没有。我想附和巴尔马所说的。在这里使用宏不仅会增加调试宏的混乱,而且无论哪种方式都需要文档。用户可能希望阅读文档,而不是从函数原型中推断出必要的信息。然而,根据您实际要做的事情,传递函数指针可能是一个更好的选择。例如,支持排序的数据结构的比较器或排序函数。与其强迫用户实现你的功能,不如给他们一个规范,让他们做他们想做的事情。你会推荐一个更好的方法或一个描述它的链接吗?Thanks@pragmatic-penguin更好的方法只是记录用户必须实现的内容。定义第一行的宏对他一点帮助都没有。我想附和巴尔马所说的。在这里使用宏不仅会增加调试宏的混乱,而且无论哪种方式都需要文档。用户可能希望阅读文档,而不是从函数原型中推断出必要的信息。然而,根据您实际要做的事情,传递函数指针