export a c++ function with it's raw function name - c++

I'm writing a dll, which exports a function
extern "C"
__declspec(dllexport)
std::list<string> create() {
return std::list<string>();
}
the compiler complains:
error C2526: 'create' : C linkage function cannot return C++ class 'std::list<_Ty>'
if I remove the extern "C", the function name exported would be:
?create##YA?AV?$list#PAUanalyzer##V?$allocator#PAUanalyzer###std###std##XZ
I want the name to be clean, so I added extern "C", now it conflicts
Any other way can get a clean function name?
Thanks.

When you say extern "C" you tell the compiler to create a function that can be called from other languages than C++ (most notably C). However, no other language than C++ have std::list, so it can not create such a function because the return type is part of the function signature in C++. And if you don't create a function which has C-compatible return type (or arguments) you can not create an extern "C" function.
If you're going to use the DLL from a C++ program there is no need for the extern "C" part. The C++ compiler and linker will be able to handle the mangled name without problems anyway.

You can return a pointer instead of the object.
extern "C" __declspec(dllexport) std::list<std::string>* createAllocated()
{
return new std::list<std::string>();
}
Due to the nature of C++, the caller will need to have the compatible ABIs.

Related

Why we should Extern "C" a struct? [duplicate]

I'm writing a C++ shared library for a C program to use. However, I have a question about extern and extern "C".
Consider the following code
My header file is like this:
#ifdef __cplusplus
extern "C" int global;
extern "C" int addnumbers(int a, int b);
#else
extern int global;
#endif
This works perfectly fine; I just have to declare
int global;
in either my .cpp or my .c file. However, what I don't understand is:
What is the difference between extern "C" and extern here? I tried commenting out extern "C" int global and it works! Why?
I know that extern "C" is used for making C linkage. That's why I have extern "C" int addnumbers(int,int). In other words, if I want to write a C++ function that is to be used in a C program, I write extern "C". Now, what about global variables - the situation is different here I guess? I want the C program to use a C++ variable named global, but I can use extern not extern "C". Why is that? This is not intuitive to me.
Comment: I don't think this is a duplicate, because I'm asking what the difference is when you use it for variables versus functions.
By attaching extern "C" to your C++ declarations (objects and functions alike) you give them "C linkage" - make them accessible from C code. If you omit this "language linkage" specification, the compiler doesn't do any effort to do proper linkage. In the case of functions, this results in failed linkage, because of mangling. In the case of global variables, everything might work fine, because variables don't need mangling.
However, on my system (MS Visual Studio), linkage between C and C++ doesn't work if I "forget" to specify the extern "C" linkage specification in the C++ header file. Example error message:
error LNK2001: unresolved external symbol "int global" (?_global)
While, when I examine a compiled C++ source code that contains the definition of global with the dumpbin utility, I see
00B 00000014 SECT4 notype External | ?global##3HA (int global)
So MS Visual Studio mangles the names of global variables, unless they have C linkage - this makes C linkage specifications mandatory.
In addition, consider the following example:
namespace example {
int global;
}
If the global variable is inside a namespace, C code will not get access to it. In this case, all compilers will require the proper linkage specification on the C++ declaration:
namespace example {
extern "C" int global;
}
Conclusion:
Use extern "C" when you want C linkage - doesn't matter if it's a function or a global variable. If it's a global variable, it may work regardless, but it's not guaranteed (and may be dangerous).
extern simply tells the compiler that the next variable(global) may not have been declared yet, but it is declared as global in a different translation unit, and during the linking stage the symbol "global" will be associated with an area in the memory.
while extern "C" is, as a few people commented, is used to solve the issue of name mangling in C++, this function will be known as addnumbers_i_i (or something similar) by the linker, while in c its symbol is addnumbers
"C++ has a special keyword to declare a function with C bindings: extern "C". A function declared as extern "C" uses the function name as symbol name, just as a C function. For that reason, only non-member functions can be declared as extern "C", and they cannot be overloaded."
There is no standard in C++ for function names generated by compiler. Keyword extern "C" instructs compiler to generate function name in C standard.
I find that extern "C" is used to make the C++ function compiled in C standard and it don't do with variables, for the solutions of function name in C and C++ are different. Such as "void foo( int x, int y )", C compiler will translate it into "_foo", while C++ compiler will translate it into "_foo_int_int".

How to remove mangling in C++

I tried to create a function which is returning a vector in C++. But when it built to dll, the function name seems to be mangled.
I tried to use the extern C but the problem is return type vector cannot support if I use extern C
Error : C Linkage function cannot return C++ class std:: Vector
Below is the code I am using
class __declspec(dllexport) TestClass
{
public:
string sClassName;
string sName;
string sDescription;
};
extern "C"
{
vector<TestClass> __declspec(dllexport) GetInfoList();
}
We see it is not problem with easy solution. Here's an involved solution. Use a non-mangled name (extern "C") with GetProcAddress to access a special function in the higher level DLL. . Define all the functions you want to call, as virtuals, in an abstract base class. Call that function above to retrieve the pointer P to a lazily instantiated concrete class with virtuals overriden. Invoke desired method through the pointer P.
vector is C++ type and so cannot be directly given under extern "C". Give the function inside a class and export the class as C Type.
extern "C"
{
class __declspec(dllexport) ClassToExport
{
vector<TestClass> GetInfoList();
};
}
Now use this class object to axcess the function.

extern and extern "C" for variables

I'm writing a C++ shared library for a C program to use. However, I have a question about extern and extern "C".
Consider the following code
My header file is like this:
#ifdef __cplusplus
extern "C" int global;
extern "C" int addnumbers(int a, int b);
#else
extern int global;
#endif
This works perfectly fine; I just have to declare
int global;
in either my .cpp or my .c file. However, what I don't understand is:
What is the difference between extern "C" and extern here? I tried commenting out extern "C" int global and it works! Why?
I know that extern "C" is used for making C linkage. That's why I have extern "C" int addnumbers(int,int). In other words, if I want to write a C++ function that is to be used in a C program, I write extern "C". Now, what about global variables - the situation is different here I guess? I want the C program to use a C++ variable named global, but I can use extern not extern "C". Why is that? This is not intuitive to me.
Comment: I don't think this is a duplicate, because I'm asking what the difference is when you use it for variables versus functions.
By attaching extern "C" to your C++ declarations (objects and functions alike) you give them "C linkage" - make them accessible from C code. If you omit this "language linkage" specification, the compiler doesn't do any effort to do proper linkage. In the case of functions, this results in failed linkage, because of mangling. In the case of global variables, everything might work fine, because variables don't need mangling.
However, on my system (MS Visual Studio), linkage between C and C++ doesn't work if I "forget" to specify the extern "C" linkage specification in the C++ header file. Example error message:
error LNK2001: unresolved external symbol "int global" (?_global)
While, when I examine a compiled C++ source code that contains the definition of global with the dumpbin utility, I see
00B 00000014 SECT4 notype External | ?global##3HA (int global)
So MS Visual Studio mangles the names of global variables, unless they have C linkage - this makes C linkage specifications mandatory.
In addition, consider the following example:
namespace example {
int global;
}
If the global variable is inside a namespace, C code will not get access to it. In this case, all compilers will require the proper linkage specification on the C++ declaration:
namespace example {
extern "C" int global;
}
Conclusion:
Use extern "C" when you want C linkage - doesn't matter if it's a function or a global variable. If it's a global variable, it may work regardless, but it's not guaranteed (and may be dangerous).
extern simply tells the compiler that the next variable(global) may not have been declared yet, but it is declared as global in a different translation unit, and during the linking stage the symbol "global" will be associated with an area in the memory.
while extern "C" is, as a few people commented, is used to solve the issue of name mangling in C++, this function will be known as addnumbers_i_i (or something similar) by the linker, while in c its symbol is addnumbers
"C++ has a special keyword to declare a function with C bindings: extern "C". A function declared as extern "C" uses the function name as symbol name, just as a C function. For that reason, only non-member functions can be declared as extern "C", and they cannot be overloaded."
There is no standard in C++ for function names generated by compiler. Keyword extern "C" instructs compiler to generate function name in C standard.
I find that extern "C" is used to make the C++ function compiled in C standard and it don't do with variables, for the solutions of function name in C and C++ are different. Such as "void foo( int x, int y )", C compiler will translate it into "_foo", while C++ compiler will translate it into "_foo_int_int".

Limitations to functions declared as `extern "C"`? C++ features still usable?

Does extern "C" do something more besides specifying an identifier should not be mangled?
Are C++ features available in functions that have been declared as extern "C"?
It only affects the name mangling so that the external visibility is clear to other applications.
extern "C" does not mean compile as C code. It means only that the function should be compiled so that it can be called from C code; what that actually affects is implementation-dependent. Anything you can do in C++ is fine inside such a function, including throwing exceptions.
You shouldn't throw exceptions from them, but otherwise you can implement the body of an extern "C" function with as many C++ features as you like.
This is perfectly fine:
MyObject myobj;
extern "C" {
int myfunc(char *c)
{ // c++ features used here
std::string s = myobj.method(....
}
}

C/C++ struct question

Suppose you have a .cpp file (that is, compiled using a C++ compiler like MSVC). In that file, you define a struct in the following way:
struct Pixel
{
float x, y;
};
In the same file, you have a line of code that will call a C function, that requires a C struct equal to Pixel. If you write:
Pixel my_pixel
// set my_pixel to something
c_func(&my_pixel);
will it work? I mean, the C++ compiler will create the object my_pixel, but it will pass it to a function that is compiled as C code (i have only a .lib of that library).
If the header file is correct, it will work, assuming the C compiler and the C++ compiler use compatible calling conventions. Make sure the header file has an appropriate extern "C" block that contains the function definition.
The reason David Schzwartz says you need an extern "C" block is that without the extern "C" block, the compiler will "mangle" the name of the C function you are calling at the point you call it. If you are calling a C function and not a C++ function, the function's definition in your library will not have a mangled name, so your executable will fail to link.
That's what you want if the function you are calling is written in C++, as name mangling allows for function name overloading. The types of each of a function's parameters are compactly encoded in the mangled function name.
Name mangling was originally provided in C++ to allow C++ object files to be linked with legacy linkers, rather than having to provide a C++-specialized linker that has explicit support for overloaded functions.
C doesn't permit function name overloading, so C function names are never mangled. To provide a prototype in C++ for a single C function you do this:
extern "C" Foo( int theInt );
If you have a whole header file full of C function prototypes and you want to #include that header from a C++ source, enclose the #include in an extern C block
extern "C" {
#include "Foo.h"
}