Export duplicated functions in two namespaces (C++) - c++

I have these two namespaces, each one containing a function with the same name, like
namespace group1 {
void add(int arg) {
}
}
namespace group2 {
void add(bool arg) {
}
}
and I specify this in the header with the declarations
#ifdef __cplusplus
extern "C" {
#endif
// My namespaces and functions prototypes here
#ifdef __cplusplus
}
#endif
and I am trying to export them into a DLL, with GCC. I get a warning about a conflict between them because they have the same name, then an error at linking time. I thought the name was mangled in the object file based on the arguments, too. I don't know if the linker cares about the namespace too. How could I make this work? Thanks.

If these are C++ functions, you have to remove the extern "C" bracketing:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus 
    }
#endif
extern "C" tells the compiler "don't mangle this name"--but (as you say) you want the mangling.

You can't really do that directly. When you use the extern "C", you are declaring that the functions are exported as if they were C functions, not C++.
This means (among other things)
Namespaces are removed, and are not considered part of the name
No name mangling due to arguments is done
The best you can do is create extern "C" functions which redirect.
#ifdef __cplusplus
extern "C" {
#endif
void group1_add(int arg);
void group2_add(bool arg);
#ifdef __cplusplus
}
#endif
And the implementations of the wrapper functions would then use either group1::add() or group2::add() as appropriate.

Related

Xcode c/c++ undefined symbols

I have a .cpp file which I declare a function
#ifndef MyFile_hpp
#define MyFile_hpp
#ifdef __cplusplus
extern "C" {
#endif
void runCode();
#ifdef __cplusplus
}
#endif
#endif
This works fine. I can call this function within my Objc. In my implementation I have an extern void that it will not let me call. It's giving the undefined symbols. I need this to build as is, the extern will be declared in a different file upon compiling. Having the extern, should this compiler just trust me and let me build?
#include "MyFile.h"
extern int runMe();
#ifdef __cplusplus
extern "C" {
#endif
void runCode() {
runMe();
}
#ifdef __cplusplus
}
#endif
I think what you are doing is probably correct.
The compiler doesn't just trust you. A C++ function is declared to the linker using additional characters, or "decorations" that define the full detail of the cclass it is a member of and all its arguments. A C function has none of that, just the raw name, so it is easy for the linker to tell the difference.

Is there any reason to use extern "C" on headers without methods?

I frequently come across C header files that contain extern "C" guards,
but don't contain any actual functions. For example:
/* b_ptrdiff.h - base type ptrdiff_t definition header */
#ifndef __INCb_ptrdiff_th
#define __INCb_ptrdiff_th
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _PTRDIFF_T
#define _PTRDIFF_T
typedef long ptrdiff_t;
#endif /* _PTRDIFF_T */
#ifdef __cplusplus
}
#endif
#endif /* __INCb_ptrdiff_th */
I know that extern "C" prevents name mangling on functions, but does it also prevent against other interfacing issues on variable and type declarations?
Is the use of extern "C" in the example above meaningless in terms of resulting compatibility?
Some compilers (it's rare) implement name mangling for variables too, not just for functions. In that case, extern "C" may be needed.
Some compilers (it's also rare, but required by the standard) implement language linkage for function types, not just names, so typedef void f(); and extern "C" { typedef void f(); } declare different types.
Also, some maintainers won't notice the absence of extern "C" if they modify the header to add functions.
I recommend you just include it.
No, extern C is not needed there, but it may be convenient to have it in all headers to make sure it is not forgotten when a new function is added.

Call a C++ function from Swift

How should I call a C++ function (no classes involved) from a Swift file?
I tried this:
In someCFunction.c:
void someCFunction() {
printf("Inside the C function\n");
}
void aWrapper() {
someCplusplusFunction();
}
In someCpluplusfunction.cpp:
void someCplusplusFunction() {
printf("Inside the C++ function");
}
In main.swift:
someCFunction();
aWrapper();
In Bridging-Header.h:
#import "someCFunction.h"
#import "someCplusplusFunction.h"
I found this answer very informative, but still I cannot make it work.
Could you point me in the right direction?
Thanks!
What does the header look like?
If you want to explicitly set the linking type for C-compatible functions in C++, you need to tell the C++ compiler so:
// cHeader.h
extern "C" {
void someCplusplusFunction();
void someCFunction();
void aWrapper();
}
Note that this isn't valid C code, so you'd need to wrap the extern "C" declarations in preprocessor macros.
On OS X and iOS, you can use __BEGIN_DECLS and __END_DECLS around code you want linked as C code when compiling C++ sources, and you don't need to worry about using other preprocessor trickery for it to be valid C code.
As such, it would look like:
// cHeader.h
__BEGIN_DECLS
void someCplusplusFunction();
void someCFunction();
void aWrapper();
__END_DECLS
EDIT: As ephemer mentioned, you can use the following preprocessor macros:
// cHeader.h
#ifdef __cplusplus
extern "C" {
#endif
void someCplusplusFunction();
void someCFunction();
void aWrapper();
#ifdef __cplusplus
}
#endif

Call C++ class member function from C (Visual Studio)

I need to call a C++ member function from a C program.
I created .cpp/.h wrapper files in the C code, wrapping the C++ member functions.
i.e.- wrapper.cpp
#include "wrapper.h"
extern "C" {
void wrap_member1()
{
Class::member1();
}
void wrap_member2()
{
Class::member2();
}
}
and wrapper.h:
#include <windows.h>
#include <stdio.h>
#include "../C++ class with members I need to call.h"
extern "C" void wrap_member1();
extern "C" void wrap_member2();
My problem is when I complie:
error C2061: syntax error : identifier 'Class'
It points to the .h declaration of the C++ class as an error. Same result as if I did not have the wrapper files....?
P.S. I also removed the "extern "C" " from the prototypes and received an error on the wrapper function:
error C2732: linkage specification contradicts earlier specification for 'wrap_member1'
Any advice?
There are two issues:
One, you are including a C++ header file in a C header file. This means the C compiler gets C++ code. This is what causes the error you are experiencing. As Reed Copsey suggests, put the #include in the C++ source file instead of the C header file.
Two, you are using extern "C" in the C header file. Wrap your statement in an #ifdef as such:
#ifdef __cplusplus
extern "C" {
#endif
/* Functions to export to C namespace */
#ifdef __cplusplus
}
#endif
This will allow the file to be usable for both C and C++.
In your wrapper you must conditionaly compile the extern "C" part, because is a C++ only construct:
wrapper.h:
#ifdef __cplusplus
extern "C" {
#endif
extern void wrap_member1();
#ifdef __cplusplus
}
#endif
In the wrapper.cpp:
extern "C" void wrap_member1()
{
Class::Member1();
}
In your C module you include only wrapper.h and link to wrapper.obj.
BTW Objective-C is capable of consuming C++, just change the name of your file from *.m to *.mm in XCode.
You need to include your class in wrapper.cpp:
#include "wrapper.h"
#include "ClassHeaderFile.h" // The header that defines "Class"
extern "C" {
void wrap_member1()
{
Class::member1();
}
void wrap_member2()
{
Class::member2();
}
}

Does extern "C" have any effect in C?

I just got some C code that uses extern "C" to declare external functions like this:
extern "C" void func();
Is this valid C? I'm getting an error at this line, but I'm not sure if it's because of this or something else.
No, it's not valid C. It should only be used in C++ code to refer to functions defined in C code. The extern "C" should be surrounded in a ifdef __cplusplus/#endif block:
// For one function
#ifdef __cplusplus
extern "C"
#endif
void func();
// For more than one function
#ifdef __cplusplus
extern "C"
{
#endif
void func1();
void func2();
#ifdef __cplusplus
}
#endif
this is a C++ notation to tell the compiler/linker to use C calling standards.
Usually that line is wrapped in an pre-processor statement.
#ifdef __cplusplus
extern "C" {
#endif
// stuff
#ifdef __cplusplus
}
#endif
Not valid in C. If present after preprocessing this will result in a diagnostic as per the standard.
For C++, this turns of name-mangling. See this for more details as to why it may be required. Can you post some more details?