具有C链接的函数能够返回类类型吗?

HS.*_*HS. 5 c++ visual-c++

我在dll中观察到一个具有C连接的函数.此函数返回类类型.我不确定这是如何实现的,因为C不理解课程.
我自己编写了一个示例dll和程序,并注意到VC++编译器显示了对此效果的警告,但并未阻止您.该程序能够使用此函数的GetProcAddress并调用它来接收返回的对象.类定义可供程序使用.
此外,如果我编写一个带有C链接的函数,该函数返回甚至不导出此类的类类型,则编译器不会发出任何警告.如果类定义可用,程序可以从dll使用此函数.
有关这是如何工作的任何想法?这样的行为编译器/平台是否具体?

ice*_*ime 10

你是在误解行为extern "C".

它仅影响该被阻止的目标文件中的函数的名字改编.它既没有"更多C"或"更少C++"的功能.extern "C"添加到C++函数的唯一附加限制是不应该重载.

  • 适用于MSVC++,不是一般的.可能存在不兼容的C和C++ ABI,而`extern"C"`函数必须使用C ABI.另外,重载一个`extern"C"`函数是合法的,只要其他重载不是`extern"C"`本身. (2认同)

Max*_*ert 5

C链接的函数可以返回无法用C表示的对象,只要它们可以在C中操作.根据我的C++设计和演变版本(第11.3.3节):

在决定实际添加到语言中的那个之前,我们考虑了类型安全联动方案的几种替代方案[Stroustrup,1988]:......

  • 仅为无法使用C函数的函数提供类型安全链接,因为它们具有无法用C表示的类型.

声明具有C链接的函数仍具有C++调用语义.也就是说,必须声明形式参数,并且实际参数必须在C++匹配和歧义控制规则下匹配....如果我们为C提供特殊服务,我们就不得不向C++编译器添加一组无限的语言调用约定[用于链接到Pascal,Fortran,PL/I等]....

链接,语言间调用和语言间对象传递本质上是困难的问题,并且具有许多依赖于实现的方面.......我希望我们没有听到这件事的最后一件事.

也就是说,C++链接不是基于所涉及的类型是否是有效的C类型.这是一个有意的设计决定.它允许您创建一个用C++编译的DLL,但可以通过标头从C中使用它:

// in the header
struct Foo; // forward declaration

#ifdef __cplusplus
extern "C" {
#endif

struct Foo* create_foo();

void destroy_foo(struct Foo*);

void foo_bar(struct Foo*);

#ifdef __cplusplus
} // extern "C"

// now declare Foo
struct Foo {
    void bar();
};
#endif

// in the implementation file
#include <iostream>
extern "C" {
    Foo* create_foo()
    {
        return new Foo();
    }

     void destroy_foo(Foo* f)
    {
        delete f;
    }

    void foo_bar(Foo* f)
    {
        f->bar();
    }
}

void Foo::bar()
{
    std::cout << "Foo::bar() called\n";
}    
Run Code Online (Sandbox Code Playgroud)

注意,在两个电话new,deletestd::cout.这些都需要C++运行时.因此,实现文件必须使用C++编译,但由于函数具有C链接,因此可以从C或C++使用标头.

那么你怎么得到一个FooC?在这种情况下,你没有,因为没有办法以C将理解的方式在标题中完全声明它.相反,C只能看到前向声明,它会创建一个不完整的类型.C不知道不完整类型有多大,所以C函数不能创建它或直接对它们进行操作,但是C确实知道指向不完整类型的指针有多大,所以C可以操作指向不完整类型的指针类型.你可以获得更多的创造力,并实际上用C++创建POD类型,你可以直接在C中操作.

只要您只Foo*在C中使用s,就不必在C中实际定义Foo结构.事实上,APR使用了类似的设计("创建APR类型",我找不到更好的链接).