在我的项目中,我们大量使用C头,它提供了一个API来与外部软件进行通信。简而言之,在我们的项目中,错误更多地出现在调用这些头文件中定义的函数上(这是一个古老而丑陋的遗留代码)。
我想在调用这些函数时实现间接,所以我可以在调用实际的实现之前包含一些分析。
因为我并不是唯一一个从事这个项目的人,所以我想以这样的方式制作这些包装器:如果有人直接使用原始实现,那么应该会导致编译错误。
如果这些头文件是C ++源代码,我可以简单地创建一个namespace
,将包含的文件包装在其中,并使用它实现我的函数(其他开发人员将能够使用原始实现::
运算符,但只是无法直接调用它对我来说是足够的封装。但是标题是C源(我必须包含extern "C"
指令包含),所以命名空间不会帮助我AFAIK。
我试着玩define
s,但没有运气,就像这样:
#define my_func api_func
#define api_func NULL
上述代码我想要的是在预处理期间将my_func
转换为api_func
,同时直接调用api_func
会产生编译错误,但是赢得了#39;工作是因为它实际上会将my_func
翻译为NULL
。
所以,基本上,我想创建一个包装器,并确保访问API的唯一方法是通过这个包装器(除非其他开发人员做出一些解决方法,但这是不可避免的)。 请注意,我需要包含数百个函数,这些函数会在整个代码中多次显示。
我的包装器必须包含那些C头,但是我想让它们在我的包装器文件之外留下范围,并使它们对包含我的包装器的每个其他文件都不可用,但我想这是在C / C ++中是不可能的。
答案 0 :(得分:1)
你有几个选择,其中没有一个很棒。
static
并将包装器放在相同的源文件中,那么您可以确保仅通过包装器调用原始函数。例如:static int api_func_real(int arg);
int api_func(int arg) {
// ... instrumentation ...
int result = api_func_real(arg);
// ... instrumentation ...
return result;
}
static int api_func_real(int arg) {
// ...
}
预处理器可以为您提供帮助,但我毫不犹豫地推荐具体信息,但没有任何细节可以使用。
#define api_func api_func_wrapper
然后,您将实现各种api_func_wrapper()
函数。
这些情况的不同之处在于,如果更改遗留函数名称,那么这些函数之间的内部调用将通过带有原始名称的包装器(除非您也更改调用),但是如果您实现包装器新名称然后它们将仅在显式调用时使用,这对于遗留代码中的内部调用不会发生(除非您再次修改这些调用)。
答案 1 :(得分:1)
您可以执行类似
的操作[你的包装器的包含文件]
int origFunc1 (int x);
int origFunc2 (int x, int y);
#ifndef WRAPPER_IMPL
#define origFunc1 wrappedFunc1
#define origFunc2 wrappedFunc2
#else
int wrappedFunc1(int x);
int wrappedFunc2(int x, int y);
#endif
[你的包装器实现]
#define WRAPPER_IMPL
#include "wrapper.h"
int wrapperFunc1 (...) {
printf("Wrapper1 called\n");
origFunc1(...);
}
您的包装器的C文件显然需要{/ 1}} #define
之前包括标头。
这既不好也不干净(如果有人想作弊,他可以简单地定义WRAPPER_IMPL
),但至少一些方式。
答案 2 :(得分:1)
在Linux中有两种方法可以包装或覆盖C函数:
Hello World from B; Hello World from A
可以在以下位置找到完整的文章:
var iTest = 0;
if (iTest) {
let sText = "This is a template string which can contain variables like ${iTest}";
console.log(sText);
} else if (!iTest) {
let fnc = (iRadius, iPi = 3.14) => {
console.log("The area of the circle with the radius ${iRadius}cm is ${Math.round(iPi * iRadius * iRadius)}cm²");
}
fnc(3.14);
} else {
/* This is never going to be called since else if is already handling the only option besides the if */
}
var fnc = (iAlpha, iBravo, cb) => {
cb(iAlpha + iBravo);
}
fnc(84,255,(iResult) => {
console.log(iResult);
});