简体   繁体   English

如何在C中实现在C ++名称空间中声明的函数?

[英]How can I implement in C a function declared in a C++ namespace?

Let's say I have a C++ header file foo.hpp : 假设我有一个C ++头文件foo.hpp

namespace foo {
    int bar(int);
}

I cannot use extern "C" because it needs to only be accessible from the namespace foo . 我不能使用extern "C"因为它只能从名称空间foo访问。

Is there a portable (or relatively portable) way to declare foo::bar in a C file foo.c so that it will link with anyone using foo::bar from C++? 有没有一种可移植的(或相对可移植的)方法在C文件foo.c声明foo::bar ,以便它可以与C ++中使用foo::bar任何人链接?

I know that on a particular system with a particular compiler, I can just find out how foo::bar is mangled and do something like this in foo.c : 我知道,在具有特定编译器的特定系统上,我可以找出foo::bar的变形方式,并在foo.c

int ZN3foo3barEi(int x) { /* ... */ }

But this is neither portable nor readable. 但这既不可移植也不可读。

extern "C" can be nested (in fact, that's how headers like <cstdio> typically work!), so you can just do the following: extern "C"可以嵌套(实际上,这就是<cstdio>这样的标头通常的工作方式!),因此您可以执行以下操作:

/* C++ code */
namespace foo {
    extern "C" {
        int bar(int);
    }
}

After that, you just implement it in C as usual: 之后,您只需照常在C中实现它即可:

/* C code */
int bar(int x) {
    return -x; /* or whatever */
}

Unfortunately, if there's a naming conflict (say, if you have both foo::bar and baz::bar ), you won't be able to have them both, unless they're the same function. 不幸的是,如果存在命名冲突(例如,如果您同时拥有foo::bar baz::bar ),除非它们具有相同的功能,否则您将无法同时拥有它们。

Would a wrapper be acceptable? 包装器可以接受吗?

namespace foo {
    int bar(int);
    }
extern "C" int callable_from_c(int f) {
    return foo::bar(f);
    }

You are forced to your backup plan (to use a wrapper function) for the following reason: C++ supports overloading of functions, and by that reason you can have different implementations of bar (with different fingerprints, even compatible) while you can have only one implementation in C. Which of the C++ possibilities would be matched for bar in case you call them from C? 不得不您的备份计划(使用一个包装函数),原因如下:C ++支持的功能超载,并通过这个原因,你可以有不同的实现bar (有不同的指纹,甚至是兼容的),而你只能有一个在C中实现。如果您从C调用它们,哪种C ++可能与bar相匹配? What if you have bar(int) and bar(long) in C++ and you want to call bar(3) from C? 如果您在C ++中具有bar(int)bar(long)并想从C调用bar(3)怎么办?

The solution is to have one wrapper extern "C" function that calls the appropiate non-C function. 解决方案是使用一个包装器extern "C"函数来调用适当的非C函数。 This function can be called from C and you'll get the desired results. 可以从C调用此函数,您将获得所需的结果。

If you look, for example, at the identifier names that the linker manages, you'll see how the compiler mangles identifiers to cope at linking time with overloading. 例如,如果您查看链接器管理的标识符名称,您将看到编译器如何处理标识符以在链接时因过载而应付。 That does not happen if you declare a function extern "C" in C++. 如果在C ++中声明函数extern "C" ,则不会发生这种情况。

Another reason is that you don't have namespaces in C. The C function version must be visible at the global namespace level. 另一个原因是您在C中没有名称空间。C函数版本必须在全局名称空间级别可见。 You are not able to hide a C calling convention inside a namespace because it is callable from all the C code or you'll be violating the C calling conventions. 您无法在命名空间中隐藏C调用约定,因为可以从所有C代码中调用它,否则您将违反C调用约定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM