在 C++ 中重新定义 C 函数
Redefine a C function in C++
我有一个带有函数的 C 库
#ifdef __cplusplus
extern "C" {
#endif
void exitWithError(const char* func) {
printf("woopsie in %s", func);
exit(1);
}
#ifdef __cplusplus
}
#endif
exitWithError
由库内部的其他 C 代码独占调用。
C 库始终在 "C mode" 中编译,即通过 g++ -x c ...
,符合 C99,因此不能包含任何 C++ 代码。 (我现在意识到这使得 #ifdef __cplusplus
检查完全多余,但是哼哼,这里不相关)。
我正在寻求在使用此 C 库的 C++14 项目中重新定义 exitWithError
,以便我可以更改处理错误的方式(请参阅我的 )。这会改变 C 库的内部行为。我试图避免更改底层 C 库代码,但这不是绝对必要的。
事实证明,在我的调用 C++ 代码中,我可以用
简单地覆盖 exit
的行为
extern "C" void exit(int status) {
throw 1;
}
这很好用,但具有调用 printf
的 C exitWithError
函数。我希望删除该行为,因此当 C 库调用 exitWithError
.
时不会打印任何内容
试图用同样的技巧重新定义 exitWithError
...
extern "C" void exitWithError(const char* func) {
throw 1;
}
在编译过程中自然会导致 duplicate symbol
错误。
exit
可以重新定义吗?有什么方法可以 "undefine" exitWithError
以便调用 C++ 代码可以重新定义它吗?
我怀疑我可以在编译用于我的 C++ 项目的 C 库时传递一个额外的编译器标志(例如 -DSILENCE_FOOL
),并将 C 库代码修改为
void exitWithError(const char* func) {
#ifndef SILENCE_FOOL
printf("woopsie in %s", func);
#endif
exit(1);
}
但我更喜欢不对 C 代码进行任何修改的方法。
最后,是否有更明智的方法(重构 C 库)允许 C 库的用户 "hook in" 或覆盖 exitWithError
行为?这是一个当用户提供不正确的参数时调用的函数(在我的 C++ 代码中,我将用 std::invalid_argument
覆盖它)。
I can, in my calling C++ code, simply override the behaviour of exit with
extern "C" void exit(int status) {
throw 1; }
exit
是C标准库保留的标识符,void exit(int)
是xitWithError C++标准库保留的函数签名。所以,除非你的目标系统是独立的,否则这个定义违反了语言标准。
Trying to redefine exitWithError with the same trick...
extern "C" void exitWithError(const char* func) {
throw 1;
}
这违反了一个定义规则。一个函数最多只能有一个定义(例外情况适用,但 none 对您有帮助)。
Is there any way to "undefine" exitWithError so that the calling C++ code can redefine it?
标准 C 或 C++ 中没有任何内容。
What about exit enabled it to be redefined?
一些编译器,例如 GCC,有一个叫做 "weak symbol"s 的特性,它允许链接器从多个不同的定义中进行选择。您使用的 C 标准库可能将 exit
定义为此类弱符号。
您可以使用相同的技术来声明 exitWithError
weak 的 C 库定义。但与其他解决方案一样,这也需要修改库。请注意,这种方法在替换 exit
和替换库函数时都是非标准的。
is there a more sensible way (refactoring the C library) to allow users of the C library to "hook in" or override the exitWithError behaviour?
可以用函数指针引入多态性。示例:
// in library (C):
void exitWithErrorDefault(const char* func) {
printf("woopsie in %s", func);
exit(1);
}
typedef void errorHandler_f(const char*);
errorHandler_f* exitWithErrorHandler = exitWithErrorDefault;
void exitWithError(const char* func) {
exitWithErrorHandler(func);
}
// usage (C++)
void exitWithErrorCpp(const char* func) {
throw 1; // bad
}
int main()
{
exitWithErrorHandler = exitWithErrorCpp;
从 C 调用的函数中抛出异常通常不是一个好主意。C 没有异常,而且 C 函数通常不是异常安全的。这通常会导致内存或其他资源泄漏。
在这种特殊情况下,可能不会尝试在调用 exitWithError
之后释放资源,因为它预计会终止进程。如果您在捕获异常后不尝试继续该过程,那么您可能不需要关心泄漏。
我有一个带有函数的 C 库
#ifdef __cplusplus
extern "C" {
#endif
void exitWithError(const char* func) {
printf("woopsie in %s", func);
exit(1);
}
#ifdef __cplusplus
}
#endif
exitWithError
由库内部的其他 C 代码独占调用。
C 库始终在 "C mode" 中编译,即通过 g++ -x c ...
,符合 C99,因此不能包含任何 C++ 代码。 (我现在意识到这使得 #ifdef __cplusplus
检查完全多余,但是哼哼,这里不相关)。
我正在寻求在使用此 C 库的 C++14 项目中重新定义 exitWithError
,以便我可以更改处理错误的方式(请参阅我的
事实证明,在我的调用 C++ 代码中,我可以用
简单地覆盖exit
的行为
extern "C" void exit(int status) {
throw 1;
}
这很好用,但具有调用 printf
的 C exitWithError
函数。我希望删除该行为,因此当 C 库调用 exitWithError
.
试图用同样的技巧重新定义 exitWithError
...
extern "C" void exitWithError(const char* func) {
throw 1;
}
在编译过程中自然会导致 duplicate symbol
错误。
exit
可以重新定义吗?有什么方法可以 "undefine" exitWithError
以便调用 C++ 代码可以重新定义它吗?
我怀疑我可以在编译用于我的 C++ 项目的 C 库时传递一个额外的编译器标志(例如 -DSILENCE_FOOL
),并将 C 库代码修改为
void exitWithError(const char* func) {
#ifndef SILENCE_FOOL
printf("woopsie in %s", func);
#endif
exit(1);
}
但我更喜欢不对 C 代码进行任何修改的方法。
最后,是否有更明智的方法(重构 C 库)允许 C 库的用户 "hook in" 或覆盖 exitWithError
行为?这是一个当用户提供不正确的参数时调用的函数(在我的 C++ 代码中,我将用 std::invalid_argument
覆盖它)。
I can, in my calling C++ code, simply override the behaviour of exit with
extern "C" void exit(int status) { throw 1; }
exit
是C标准库保留的标识符,void exit(int)
是xitWithError C++标准库保留的函数签名。所以,除非你的目标系统是独立的,否则这个定义违反了语言标准。
Trying to redefine exitWithError with the same trick...
extern "C" void exitWithError(const char* func) { throw 1; }
这违反了一个定义规则。一个函数最多只能有一个定义(例外情况适用,但 none 对您有帮助)。
Is there any way to "undefine" exitWithError so that the calling C++ code can redefine it?
标准 C 或 C++ 中没有任何内容。
What about exit enabled it to be redefined?
一些编译器,例如 GCC,有一个叫做 "weak symbol"s 的特性,它允许链接器从多个不同的定义中进行选择。您使用的 C 标准库可能将 exit
定义为此类弱符号。
您可以使用相同的技术来声明 exitWithError
weak 的 C 库定义。但与其他解决方案一样,这也需要修改库。请注意,这种方法在替换 exit
和替换库函数时都是非标准的。
is there a more sensible way (refactoring the C library) to allow users of the C library to "hook in" or override the exitWithError behaviour?
可以用函数指针引入多态性。示例:
// in library (C):
void exitWithErrorDefault(const char* func) {
printf("woopsie in %s", func);
exit(1);
}
typedef void errorHandler_f(const char*);
errorHandler_f* exitWithErrorHandler = exitWithErrorDefault;
void exitWithError(const char* func) {
exitWithErrorHandler(func);
}
// usage (C++)
void exitWithErrorCpp(const char* func) {
throw 1; // bad
}
int main()
{
exitWithErrorHandler = exitWithErrorCpp;
从 C 调用的函数中抛出异常通常不是一个好主意。C 没有异常,而且 C 函数通常不是异常安全的。这通常会导致内存或其他资源泄漏。
在这种特殊情况下,可能不会尝试在调用 exitWithError
之后释放资源,因为它预计会终止进程。如果您在捕获异常后不尝试继续该过程,那么您可能不需要关心泄漏。