I want to pass the pointer of an instance of a template function to a C function as callback. And It's obviously impossible to declare the template in extern "C".
Is it guaranteed that C++ uses the same calling convention with C for nonmember function? And is there any other effect of declaring a function in extern "C" besides it prevents incompatible name mangling?
Its a bad idea to export C++ methods or template functions directly for a C library. If I have a C++ program then I usually put the C bindings into its separate .cpp + .h file pair and I surround the header file with and extern "C" block and I use only C compatible function declarations there. In the accompanying .cpp file you implement the functions and since its a .cpp file you can access C++ features (templates, classes, ...) in the actual implementation of the binding functions even if their signature is C compatible using C-friendly types.
In your case this case you should put a C binding function into this binder .cpp+.h file and from the implementation of that function you would be able to call an instance of the specified template function easily.
Simple stupid example:
CBindings.h:
// This is the header used by both C++ and C
#ifdef __cplusplus
extern "C" {
#endif
// C compatible function declarations with C-friendly types.
int int_from_string(const char* s);
#ifdef __cplusplus
}
#endif
CBindings.cpp:
#include "CBindings.h"
#include "WhateverCPPHeader.h"
int int_from_string(const char* s)
{
// Since the implementation is in a .cpp file here we can do C++ish things.
return FromString<int>(s);
}
WhateverCPPHeader.h:
// Somewhere in your C++ header files:
template <typename T>
T FromString(const std::string& s);
...
// Template specializations of FromString for several T types
...
Whatever.c:
#include "CBindings.h"
#include <stdio.h>
void my_c_func(void)
{
int i = int_from_string("5");
printf("%d\n", i);
}
This works on all platforms without problems and the cut between C/C++ is clearly separated into its own file.
No. It's not guaranteed that it uses the same calling convention. You can use the calling convention modifiers like _stdcall, cdecl, pascal, etc. So you have to make sure that both sides know the same calling convention.
One way would be detecting the mangled name and define a proper prototype for the C function.
Consider changing the design; since you can't benefit from the template in C anyway, you can define a simple C++ function (defined extern "C") that calls the templated function.
Related
I have a DLL in pure C code. I would like to find a way to remove the library name prefix from the functions, classes, and structs; EX:
// lib.h
void foobar();
// lib.hpp
namespace foo {
bar();
}
I would like to avoid simply writing a wrapper for every function, since I'd have to write it for every time I want to add a function. Is there a better / more efficient way of writing this?
I started writing the wrapper idea, but there's a lot of functions to write this for. Void pointers worked a little better, but still had the same issue.
Unless you are worried about name conflicts between existing C++ function names and the C library, how about just using extern "C" (in your C++ code) and call it (from your C or C++ code). For example:
extern "C" void f(int); // apply to a single function
extern "C" { // or apply to a block of functions
int g(double);
double h(void);
};
void code(int i, double d)
{
f(i);
int ii = g(d);
double dd = h();
// ...
}
When code is enclosed within an extern “C” block, the C++ compiler ensures that the function names are un-mangled – that the compiler emits a binary file with their names unchanged, as a C compiler would do.
This approach is commonly used to accommodate inter language linkage between C++ and C.
from this Reference
more from cppprefference.com
You could try this:
// lib.hpp
namespace foo {
constexpr auto bar = foobar;
}
This should create a function pointer, and because it is constexpr, it should get resolved at compile time, so no performance hit. Also, constexpr is implicitly inline, so that (or static) can be omitted from this definition.
I am attempting to write use the this C library without modification in a C++ application. It uses C11 atomics.
Consider the following program, which we can put in a file called main.cc.
#include "mpscq.h"
int main(){}
If I compile this with the g++ -std=c++11 -c main.cc, I get a whole collection of errors that look like the following.
usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdatomic.h:68:9: error: ‘_Atomic’ does not name a type
typedef _Atomic __UINT_FAST32_TYPE__ atomic_uint_fast32_t;
^
/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdatomic.h:69:9: error: ‘_Atomic’ does not name a type
typedef _Atomic __INT_FAST64_TYPE__ atomic_int_fast64_t;
Is it possible to fix these errors without any modification to the library code?
That is, I am willing to use whatever magic incantations are needed in my c++ code or my compiler flags, but I'd rather not change the library code.
I have seen this answer but it requires modification of the header file.
Is it possible to fix these errors without any modification to the library code?
C++ does not have an _Atomic type qualifier, but the structure declared in the library header has members, including the first, with _Atomic-qualified type. C++ will not accept this (and wrapping the header inclusion in an extern "C" block will not help).
C allows objects of _Atomic-qualified type to have different representations than objects of the non-_Atomic version of the same type, so in a general sense, this means that C++ cannot directly access any members of any instance of that structure.
If your C implementation happened to use the same representation for corresponding _Atomic and non-_Atomic types, then you could probably make your C++ compiler accept the header by #defineing the symbol _Atomic to an empty string, but this would be a gateway to more subtle bugs. You could not expect C++ to provide the atomic access semantics that the library expects, so even in this case C++ cannot safely access the structure's members (directly).
If it is sufficient to manipulate instances of the struct only via the provided functions, then you can do so via opaque pointers. Create a version of the header that provides a forward declaration of the structure, but no definition, and that provides all the function declarations (with C linkage). You C++ code should accept the header and be able to call the functions, both receiving and returning pointers to instances of the structure that it must never try to dereference.
#ifndef __MPSCQ_H
#define __MPSCQ_H
#ifdef __cplusplus
extern "C" {
#endif
struct mpscq;
struct mpscq *mpscq_create(struct mpscq *n, size_t capacity);
// other functions ...
#ifdef __cplusplus
}
#endif
#endif
If you need more than the existing functions provide, then you'll need to write additional helper functions, in C.
You do not need wrapper for using that mpscq in C++ code but you need different
header to include it. That would work:
#ifndef MPSCQ_H_FOR_CPP
#define MPSCQ_H_FOR_CPP
extern "C"
{
struct mpscq;
mpscq *mpscq_create(mpscq *n, size_t capacity);
bool mpscq_enqueue(mpscq *q, void *obj);
void *mpscq_dequeue(mpscq *q);
size_t mpscq_count(mpscq *q);
size_t mpscq_capacity(mpscq *q);
void mpscq_destroy(mpscq *q);
}
#endif
That said I would anyway write a wrapper to take care of RAII and such.
Let's say I have a C++ header file foo.hpp:
namespace foo {
int bar(int);
}
I cannot use extern "C" because it needs to only be accessible from the namespace foo.
Is there a portable (or relatively portable) way to declare foo::bar in a C file foo.c so that it will link with anyone using foo::bar from C++?
I know that on a particular system with a particular compiler, I can just find out how foo::bar is mangled and do something like this in foo.c:
int ZN3foo3barEi(int x) { /* ... */ }
But this is neither portable nor readable.
extern "C" can be nested (in fact, that's how headers like <cstdio> typically work!), so you can just do the following:
/* C++ code */
namespace foo {
extern "C" {
int bar(int);
}
}
After that, you just implement it in C as usual:
/* C code */
int bar(int x) {
return -x; /* or whatever */
}
Unfortunately, if there's a naming conflict (say, if you have both foo::bar and baz::bar), you won't be able to have them both, unless they're the same function.
Would a wrapper be acceptable?
namespace foo {
int bar(int);
}
extern "C" int callable_from_c(int f) {
return foo::bar(f);
}
You are forced to your backup plan (to use a wrapper function) for the following reason: C++ supports overloading of functions, and by that reason you can have different implementations of bar (with different fingerprints, even compatible) while you can have only one implementation in C. Which of the C++ possibilities would be matched for bar in case you call them from C? What if you have bar(int) and bar(long) in C++ and you want to call bar(3) from C?
The solution is to have one wrapper extern "C" function that calls the appropiate non-C function. This function can be called from C and you'll get the desired results.
If you look, for example, at the identifier names that the linker manages, you'll see how the compiler mangles identifiers to cope at linking time with overloading. That does not happen if you declare a function extern "C" in C++.
Another reason is that you don't have namespaces in C. The C function version must be visible at the global namespace level. You are not able to hide a C calling convention inside a namespace because it is callable from all the C code or you'll be violating the C calling conventions.
In *.h header files of a C library, should one declare functions
extern void f();
// or only
void f();
when using only in C
when using from C++.
There's [almost] never any need to use the keyword extern when declaring a function, either in C or in C++. In C and in C++ all functions have external linkage by default. The strange habit of declaring functions in header files with extern probably has some historical roots, but it has been completely irrelevant for decades already.
There's one [obscure?] exception from the above in C, which is probably not directly related to what you are asking about: in C language (C99) if in some translation unit a function is defined as inline and also declared as extern (an explicit extern is used) then the inline definition of that function also serves as an external definition. If no declarations with explicit extern are present in the translation unit, then the inline definition is used as "internal" definition only.
P.S. There's such thing as extern "C" in C++, but that is a completely different matter.
In header files of a C library, should one declare functions:
extern void f();
// or only
void f();
Issue 1: Semantics
In a C++ program, the functions are declared as functions returning no value and taking no arguments.
In a C program, the functions are declared as functions returning no value and taking an indeterminate but not variable-length list of arguments.
To get the 'no arguments' meaning in C, use one of:
extern void f(void);
void f(void);
The same notation also means the same thing in C++, though for pure C++ code, using void in the argument list is not idiomatic (do not do it in pure C++ code).
Issue 2: Inter-working between C and C++
Tricky, but the normal rule would that you should declare the functions to C++ code as extern "C". To use the same source code for both, you then need to test the __cplusplus macro. You'd normally do something like:
#ifdef __cplusplus
#define EXTERN_C extern "C"
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C /* Nothing */
#define EXTERN_C_BEGIN /* Nothing */
#define EXTERN_C_END /* Nothing */
#endif
EXTERN_C void f(void);
EXTERN_C_BEGIN
void f(void);
int g(int);
EXTERN_C_END
The options and variations are manifold, but the header can be used by both C and C++.
The macros would normally be defined in one general-purpose header that's used everywhere, and then the particular header would ensure that the general purpose header is included and then use the appropriate form of the macro.
Issue 3: Style
Formally, there is no need for the extern notation before a function declaration. However, I use it in headers to emphasize that it is a declaration of an externally defined function, and for symmetry with those (rare) occasions when there is a global variable declared in the header.
People can, and do, disagree over this; I go with the local rules — but when I'm the rule-maker, the extern is included in a header.
For general use declare as
#ifdef __cplusplus
extern "C" {
#endif
void f(void);
#ifdef __cplusplus
}
#endif
Otherwise, extern is obsolete.
The latter is perfectly fine, since it's only a function definition, which tells those, who include this header: 'There's a function with this prototype somewhere around here'
In this context, functions differ clearly from variables, but that's a different matter.
Make sure though, that you do not include the function body, unless you declare it 'inline' or as part of a class definition (C++) or as a 'template function' (also C++).
Specifying extern in function prototype has no effect, since it is assumed by default. Whenever a compiler sees a prototype, it assumes a function is defined somewhere else (in the current or another translation unit). This holds for both of the languages.
The following thread has some useful comments in general about extern.
Effects of the extern keyword on C functions
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"
}