为什么需要“extern C"?对于 C 函数的 C++ 回调?

2022-01-03 00:00:00 c callback c++ extern-c

我在 Boost 代码中找到了这样的例子.

I find such examples in Boost code.

namespace boost {
   namespace {
     extern "C" void *thread_proxy(void *f)
     {
       ....
     }

   } // anonymous
   void thread::thread_start(...)
   {
       ...
       pthread_create(something,0,&thread_proxy,something_else);
       ...
   }
} // boost

为什么你真的需要这个extern "C"?

Why do you actually need this extern "C"?

很明显 thread_proxy 函数是私有的内部函数,我不希望它将被修改为thread_proxy",因为我实际上根本不需要它修改.

It is clear that the thread_proxy function is private internal and I do not expect that it would be mangled as "thread_proxy" because I actually do not need it mangled at all.

事实上,在我编写并在许多平台上运行的所有代码中,我从未使用过 extern "C" 并且这在正常函数中正常工作.

In fact, in all my code that I had written and that runs on many platforms, I never used extern "C" and this had worked as-is with normal functions.

为什么要添加extern "C"?

我的问题是 extern "C" 函数污染了全局命名空间,实际上它们并没有像作者期望的那样隐藏.

My problem is that extern "C" functions pollute the global namespace and they are not actually hidden as the author expects.

这不是重复的!我不是在谈论重整和外部链接.很明显,这段代码不需要外部链接!

This is not a duplicate! I'm not talking about mangling and external linkage. It is obvious in this code that external linkage is unwanted!

答案: C 和 C++ 函数的调用约定不一定相同,因此需要根据 C 调用约定创建一个.参见 C++ 标准 7.5 (p4).

Answer: The calling conventions of C and C++ functions are not necessarily the same, so you need to create one with the C calling convention. See 7.5 (p4) of C++ standard.

推荐答案

很明显,thread_proxy 函数是私有的内部函数,我不希望它被修改为thread_proxy",因为我实际上根本不需要它修改.

It is clear that the thread_proxy function is private internal and I do not expect that it would be mangled as "thread_proxy" because I actually do not need it mangled at all.

无论如何,它仍然会被破坏.(如果不是 extern "C") 编译器就是这样工作的.我同意编译器可以说这不一定需要被破坏"是可以想象的,但标准对此没有任何说明.也就是说,重整并没有在这里发挥作用,因为我们没有尝试链接到该函数.

Regardless, it's still going to be mangled. (Had it not been extern "C") That's just how the compiler works. I agree it's conceivable a compiler could say "this doesn't necessarily need to be mangled", but the standard says nothing on it. That said, mangling doesn't come into play here, as we aren't trying to link to the function.

事实上,在我编写并在许多平台上运行的所有代码中,我从未使用过 extern "C" 并且这在正常函数中正常工作.

In fact, in all my code that I had written and that runs on many platforms, I never used extern "C" and this had worked as-is with normal functions.

在不同平台上编写与extern "C"无关.我希望所有标准 C++ 代码都能在具有标准 C++ 兼容编译器的所有平台上运行.

Writing on different platforms has nothing to do with extern "C". I expect all standard C++ code to work on all platforms that have a standard C++ compliant compiler.

extern "C" 与 C 接口有关,pthread 是 C 的库.它不仅不会破坏名称,还确保它可以使用 C 调用约定进行调用.这是需要保证的调用约定,因为我们不能假设我们在某个编译器、平台或体系结构上运行,所以尝试这样做的最佳方法是使用给我们的功能:extern"C".

extern "C" has to do with interfacing with C, which pthread is a library of. Not only does it not mangle the name, it makes sure it's callable with the C calling convention. It's the calling convention that needs to be guaranteed, and because we can't assume we are running on a certain compiler, platform, or architecture, the best way to try and do that is with the functionality given to us: extern "C".

我的问题是 extern "C" 函数污染了全局命名空间,实际上它们并没有像作者期望的那样隐藏.

My problem is that extern "C" functions pollute the global namespace and they are not actually hidden as the author expects.

上面的代码没有任何污染.它位于未命名的命名空间中,无法在翻译单元之外访问.

There's nothing polluting about the above code. It's in an unnamed namespace, and not accessible outside the translation unit.

相关文章