虽然我在SO上阅读了与此类似的问题,但似乎没有一个问题能解决我的问题。
我有一个仅限标题的实用程序,我们称之为hutil.h
,它包含一个函数,我们称之为hutil_func
。我创建了一个小工具,它有一个头文件,我们称之为tool.h
,还有一个源文件,我们称之为tool.c
。在tool.c
我实现了一些使用hutil_func
的“额外功能”,但我不想强迫用户使用hutil.h
文件,如果用户不需要额外的功能。
因此我们假设用户有一个main.c
文件,如下所示:
// #include "hutil.h" <-- How to handle if this is removed?
#include "tool.h"
int main(void)
{
a_function_from_tool(); // <-- This can use hutil_func if hutil.h included
return 0;
}
现在,我正在寻找一个解决方案 - 希望是一个在编译时处理这种情况的宏 - 它将用hutil_func
空替换#define hutil_func()
。
提前致谢!
UPDATE1:
hutil.h
无法包含在tool.c
中,因为这正是我想要避免的:如果用户不想使用hutil.h
,则用户不会将其放置在tool.c
旁边。
UPDATE2:
在hutil_func
内调用函数a_function_from_tool
。
答案 0 :(得分:2)
编辑 oops,误读了这个问题。我的坏。
如果您在tool.h
中有代码或只是声明,那么整个事情取决于。
如果你有代码,那么你应该能够利用hutil.h
文件的典型保护机制。在hutil.h
文件中,您应该有以下行:
#ifndef HUTIL_H_
#define HUTIL_H_
...
#endif
在tool.h
中,您使用以下方法保护从工具调用该函数的代码:
#ifdef HUTIL_H_
hutil_func();
#endif
只有在tool.h
中的代码可以通过这种方式加以保护时,这才有效。
要实现此目的,tool.h
是一个仅限标题的文件,您将需要一些间接。
首先,您需要能够告诉tool.h
中的例程它应该能够使用的函数(这可以使用结构指针扩展N个条目),因此我们修改了{{ 1}}例程采用额外的参数hutil_func,它是一个指向与hutil_func的调用模式匹配的函数的指针,并为例程提供与调用它时使用的名称不同的名称,例如tool.h
,所以它看起来像:
a_function_from_tool_internal
在void a_function_from_tool_internal((void)(*utilfunc)(void), other_parameters);
中,在调用代码的地方,检查utilfunc是否为tool.c
:
NULL
然后我们将以下内容放在if (utilfunc != NULL)
utilfunc();
:
tool.h
这种东西很丑陋,如果你使用的是#ifdef HUTIL_H_
#define a_function_from_tool(other_parameters) a_function_from_tool(hutil_func, other_parameters)
#else
#define a_function_from_tool(other_parameters) a_function_from_tool(0, other_parameters)
#endif
,它就会失败,但它可能会让你获得你正在寻找的那种功能。
答案 1 :(得分:2)
使用标题尝试这样做似乎是一个糟糕的设计,并打破了模块化。
将此指定为编译时选项可能更好。您的用户可以使用某种配置脚本,也可以直接修改您的makefile,因此如果他们选择使用此功能,您最终会调用类似的内容:
gcc -o tool.o tool.c -c -DUSE_HUTILS
然后,在tool.c
中,您可以执行以下操作:
#ifdef USE_HUTILS
#include "hutils.h"
#endif
...
int a_function_from_tools(void) {
/* Some code */
#ifdef USE_HUTILS
int n = hutil_func();
#else
int n = get_n_some_other_way();
#endif
return n;
}
这样,tool.c
不依赖于main.c
,也不关心#ifdef USE_HUTILS
#include "hutils.h"
#else
#include "hutils_fake.h"
#endif
中包含的内容,它应该是什么样的内容。
如果它可以适用于您正在执行的特定代码,则可以通过执行以下操作来避免函数内的多个条件编译块:
hutils_fake.h
其中hutils.h
包含与#define hutil_func()
相同的接口,但该接口基本上扩展为您所谓的“空#ifdef USE_HUTILS
宏”。或者,您可以在hutils.h
本身内检查{{1}},并定义实际功能(如果已定义),如果不是,则定义假功能。
在这些方面做一些事情来提供不同的功能,可以选择将其编译到应用程序中或从应用程序中编译出来是非常正常的。
答案 2 :(得分:0)
您可以在tool.c中包含hutil.h.在这种情况下,hutil.h在main.c中不可见。