外部C不能在类级别使用?(extern C can not be used at class lev

2019-06-23 20:08发布

只是想在Windows环境中确认,2008年VSTS + C ++项目,我们可以仅适用外部C运作水平,无法适用于类级别(以便从类用C语言名的所有成员函数重整)? 我曾尝试多种方法,但总是编译错误。

在此先感谢,乔治

Answer 1:

您可以排序的应用extern "C"通过一个非常令人费解的(但是完全合法的)成员函数的破解:

extern "C" typedef int bar_t(int x);

struct foo {
     bar_t bar; // yes, this declares a nonstatic member function!
};

int foo::bar(int x) { return x; } // definition

这根据ISO C ++ 03 9.3 [class.mfct] / 9是可能的:

一个成员函数可以使用用于功能类型一个typedef声明(但不限定)。 所得的成员函数正是因为它本来如果进行了明确规定说明符的功能,请参见8.3.5同一类型。

然而,这并不能真正买任何东西,因为ISO C ++ 03 7.5 dcl.link / 4:

AC语言联动为类成员和类成员函数的成员函数类型的名字被忽略。



Answer 2:

为extern“C”使用C风格的链接; 也就是说,原始函数名是从图书馆什么暴露。 因为它只是一个原始函数名,没有C ++的 - 只有功能将与它合作,包括在命名空间,类,结构或联合的方法或extern数据,成员。

澄清 :结构和联合是C,但没有成员函数,所以在C ++中的成员函数不能在C风格的出口(与结构和联合定义,不需要出口,因为它已经在头)



Answer 3:

恐怕不是。 但是,如果你想要的C ++的对象传递给C函数,您可以参考以下链接: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.8



Answer 4:

看着你放在一个以前的答案评论(“[M]ÿ问题是,我们只是是否适用extern C的一流水平,使类中的所有功能,自动拥有空调风格名称重整?”,答案是“ extern "C"并不完全工作方式“。

语法上, extern "C"可以应用到一个卷曲分隔块的任一个语句:

extern "C" int my_foo(int i)
{
    ...
}

extern "C" {
    int my_bar(int i)
    {
        ...
    }

    int my_baz(int i)
    {
        ...
    }
}

这是通常使用extern "C"用适当#ifdef __cplusplus在整个C头警卫。

语义上,施加的实际效果extern "C"只适用于“正常”(即,非类)函数和函数指针。 当然,你不能把它应用到一个C ++模板。 你也不能将其应用到类方法(因为一个类的方法需要知道它被称为在哪个对象,以及C风格的链接没有任何办法传递给函数的信息)。

可以应用extern "C"上存在命名空间中的功能,而是通过C.使用时命名空间的信息将完全消失


更新

如果你已经有了一个类(我们将使用一个POD类为简单起见),你想让它在C可用,你需要申请extern "C"的函数调用在C很不幸,这甚至会丑陋在简单的情况:

// in the header file
#ifdef __cplusplus
namespace X {
#endif
    struct A
    {
        int x;
#ifdef __cplusplus
        A() : x(5) { }
        int foo()
        {
             return x += 5;
        }
#endif
    };
#ifdef __cplusplus
    extern "C" {
#endif
        int A_foo(struct A a);
        struct A A_create();
#ifdef __cplusplus
    }
}
#endif


// in the .cc file
#include "try.h"

namespace X {
    extern "C" {
        int A_foo(A* a)
        {
            return a.foo();
        }

        A A_create()
        {
            return A();
        }
    }
}

// in the .c file
#include <stdio.h>
#include "try.h"

int main()
{
    struct A a = A_create();
    printf("%d", A_foo(a));
}

使用gcc你编译这个如下:

  • C ++的文件: g++ try.cc -c -o try.o
  • C文件: gcc try.c try.o

有几个要点:

  • 如果你的C ++文件调用到幕后的STL,或者调用newdelete (或new[]delete[]就需要到最终的程序链接到C ++运行时库(gcc的这个命令行开关-lstdc++
  • 你可能会想既编译C和C ++代码时,通过相同的优化参数(优化会影响对象的大小,如果大小不匹配,你可以进入很多麻烦)。 同上,用于多线程。
  • 您可以使用异常所有你想要的C ++代码,但一旦越过C代码,全盘皆输 。
  • 如果你想更复杂的东西,你可能会想看看PIMPL模式。
  • 当struct掉下来的C代码范围C ++析构函数叫(一些编译器可能答应这样做,但它不是标准)。 如果您需要做任何清理这些对象,你需要调用一个外部的“C”功能,调用析构函数。

显式调用析构函数:

extern "C" void A_destroy(struct A a)
{
    a.~A();
}


Answer 5:

嗯...... extern "C"势力C风格的联动。 它不能与类AFAIK使用。



文章来源: extern C can not be used at class level?