C-linked functions capable of returning a class type?

I watched a function in a dll that has a C link. This function returns the type of the class. I am not sure how this became possible since C does not understand the class.
I wrote a sample dll and the program itself and noted that the VC ++ compiler shows a warning about this, but does not stop you. The program is capable of GetProcAddress for this function and calls it to get the returned object. A class definition was available for the program.
In addition, if I write a C-linked function that returns the type of a class when this class is not even exported, the compiler does not give any warnings. A program can use this function from a dll provided that the class definition becomes available to it.
Any thoughts on how this works? Is this behavior compiler / platform specific?

+4
source share
3 answers

You misunderstand the behavior of extern "C" .

It affects only the function name in the object file, preventing the name mangling . It does not perform the functions neither more than C, nor less than C ++. The only additional restriction that extern "C" adds to the C ++ function is that it should not be overloaded.

+10
source

It is possible that C-linked functions return objects that cannot be expressed in C while they can be processed in C. According to my copy of Design and Evolution of C ++ (section 11.3.3):

We examined several alternatives to type binding schemes before deciding what was actually added to the language [Stroustrup, 1988]: ...

  • provide type binding only for functions that cannot be C functions, because they have types that cannot be expressed in C ....

A function declared by C-C binding still has the semantics of C ++ invocation. That is, formal arguments must be declared, and the actual arguments must comply with C ++ compliance rules and ambiguity rules .... If we provided special services for C, we would be required to add an unlimited set of language calling conventions for C ++ compilers [for links to Pascal, Fortran, PL / I, etc.] ....

Linking, interlanguage calls, and interlanguage transfer of objects are inherently difficult problems and have many implementation-related aspects .... I expect that we have not heard the last of this question.

That is, C ++ communication is not based on whether the types involved are valid types of C. This is an intentional design decision. This allows you to create a DLL compiled in C ++, but which can be used with C through the header:

 // 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"; } 

Note the calls to new , delete and std::cout . All this requires C ++ runtime. Therefore, the implementation file must be compiled with C ++, but since functions have a C link, the header can be used with C or C ++.

So how do you get Foo in C? In this case, you will not do this, because there is no way to fully declare it in the header so that C understands. Instead, C only sees the forward declaration, which creates an incomplete type. C does not know how large an incomplete type is, so C functions cannot create it or work with them directly, but C knows how large a pointer to an incomplete type is, so C can work with a pointer to an incomplete type. You can get a lot more creativity and actually create POD types in C ++, with which you can work directly in C.

As long as you use only Foo* in C, you donโ€™t need to actually define the structure of Foo in C. It so happens that APR uses a similar project ("Creating an APR Type", I could not find a better link).

+4
source

A class object is basically just a struct object, with some additional โ€œhiddenโ€ members for vtbl, etc.

However, I'm not sure what you mean by "a program can use this function, provided that the class definition becomes available to it." C throws a compiler error when viewing class Blah { ... }; .

0
source

Source: https://habr.com/ru/post/1336274/


All Articles