c++ call c function if it does exist - c++

I have some C++ code that is automatically generated to wrap some C code.
The C code has a predictable structure with the exception that it has/has not a certain function.
Since the C++ code is derived from a description that does not have this information. I would like to use the template processor to decide if this function can be called.
small example:
struct SomeStruct{
int indicatorMember;
};
extern "C" void someFun(struct SomeStruct* somePointer){
}
void someCPPcode(){
SomeStruct s;
// do something
someMechanismToCall_someFunIfExists(&s);
// do something other
}
How does someMechanismToCall_someFunIfExists have to look like, so that someCPPcode can be compiled/run in cases there someFun does exist and if it does not exist?
Is this even possible?
It would also be possible to decide if this function exists, if a certain member is part of a structure.
so, if indicatorMember does exist, the function also exists.

You might use overload with lower priority to solve your issue:
// "C-Header"
struct SomeStruct
{
int indicatorMember;
};
// Present or not
extern "C" void someFun(struct SomeStruct* somePointer){
}
// Fallback
void someFun(...) { /*Empty*/ }
void someCPPcode()
{
SomeStruct s;
// do something
someFun(&s);
// do something other
}
it would also be possible to decide if this function exists, if a certain member is part of a structure. so, if indicatorMember does exist, the function also exists.
There are several ways to detect presence of member, such as use of std::experimental::is_detected.
but outside template, you still have issue:
decltype(auto) someFunIfExists([[maybe_unused]] SomeStruct* p)
{
if constexpr (has_someFunc<SomeStruct>::value) {
return someFun(p); // Not discarded as you might expect -> Error
}
}
as if constexpr (false) { static_assert(false); } is invalid).
So you have to wrap the function inside template:
template <typename T>
decltype(auto) someFunIfExists([[maybe_unused]] T* p)
{
if constexpr (has_someFunc<T>::value) {
return someFun(p);
}
}
void someCPPcode(){
SomeStruct s;
// do something
someFunIfExists(&s);
// do something other
}

The question of whether there's a definition of some symbol with external linkage or not is inherently a question that can only be answered during linking. There is no way for the compiler to know during compilation of an individual C++ source file whether there is going to be a definition of some external function somewhere else. SFINAE can, in the best case, check for whether a certain function is declared. It is impossible for SFINAE to determine whether the linker will find a definition of that function later on.
If the C library comes with headers that you can include in C++ and that declare the functions in question only if the particular version of the C library defines them, you can use an appraoch like the one described in Jarod42's answer.
Otherwise, the best thing I can think of to do here would be to define default implementations of your functions as weak symbols that are always defined, e.g.:
struct SomeStruct
{
int indicatorMember;
};
extern "C" void someFun(SomeStruct* somePointer) __attribute__((weak))
{
// do whatever this should do in case the C library does not define this function
}
Weak symbols are no part of Standard C++, so the exact mechanism for doing this depends on your compiler and platform. The above would be an example for GCC. MSVC has an undocumented linker flag /alternatename that allows to provide default definitions for a symbol, see this answer.
During linking, if the linker finds a non-weak definition of the same symbol coming from your C library, it will pick that one, otherwise it will pick your default implementation…

Related

Avoid compiling definition of inline function multiple times

I have a non-template struct in a header file:
struct X {
constexpr X() : /* ... */ { /* ... */ }
constexpr void f() {
// ...
}
};
With functions of varying size. This is used in a lot of different translation units, and each function appears in multiple object files for them to be discarded in the final executable.
What I want is for the definitions to be in a single object file, and the other translation units can either inline the function or use an external definition (something like the extern inline semantics from C). How can I do that?
It seems to work with templates and extern template:
namespace detail {
template<std::nullptr_t>
struct X_base {
constexpr X_base() // ...
constexpr void f() // ...
};
extern template struct X_base<nullptr>;
}
struct X : detail::X_base<nullptr> {
using X_base::X_base;
};
// X.cpp
#include <X.hpp>
template struct detail::X_base<nullptr>;
But are there any major downsides to this (longer symbol names, confusing to read, needs documentation, etc.), or are there any easier ways to do this?
C++ doesn’t have the notion of an inline function that must be emitted in one translation unit and which therefore certainly need not be emitted anywhere else. (It doesn’t have the notion of emitting object code at all, but the point is that there’s no syntax that says “I promise this definition is ODR-identical to the others except that it and only it bears this marker.” so that compilers could do that.)
However, the behavior you want is the obvious way of implementing C++20 modules: because the definition of an inline function in a module is known to be the only definition, it can and should be emitted once in case several importing translation units need an out-of-line copy of it. (Inlining is still possible because the definition is made available in a compiler-internal form as part of building the module.) Bear in mind that member functions defined in a class in a module are not automatically inline, although constexpr still implies it.
Another ugly workaround is to make non-inline wrappers to be used outside of constant evaluation, although this could get unwieldy if there were multiple levels of constexpr functions that might also be used at runtime.

Warning about shadowed type definitions

Situation as follows:
in a codebase a header which defines some types, mostly convinient shortcuts like u64 for uint64_t exists. These definitions are global, as general type definitions do not really make sense when encapsulated in a namespace. This header is used in almost any other file to unify the codebase.
Also a public availible header only library is used, which happens to define the same name. In fact the other definition is not a type but a parameter name like:
void function(uint64_t u64);
Now the compiler throws warnings about that the parameter name shadows the global type definition. Which is correct in some respect.
But as the common global type-management header is needed and the include for the library is also needed, my question is how to resolve that problem in a sane way.
Also, why a type name can be shadowed by a function parameter/argument name, as a variable name and a typename are two very different things. That sounds more like a bug in the compiler to me. Without having sound knowlege about the standard in that topic, I would assume
using mytype = unsigned int;
void myfunc(mytype mytype);
to be valid, as I just have defined a variable to have the same name as a type, but the compiler can always distinguish both, because of the syntax.
Additional Question:
why the include order of both headers seems to have no effect.
I tried to solve the problem by including the external library header first (so the global type shortcut should not exist in that module) and included the common global header which defines the types later. But the Warnings persist.
Edited to preceise the problem (2 times)
But as the common global type-management header is needed and the include for the library is also needed, my question is how to resolve that problem in a sane way.
One thing you could do is to isolate the code that utilized the headers that produce that error and move it into its own compilation unit for which you silent that shadowing error message.
Also, why a type name can be shadowed by a function parameter/argument name, as a variable name and a typename are two very different things.
They are two different things, but there are cases where the syntax for both would be the same, so the compiler has to decide whether to use the parameter or the type.
Here one example, with static_assert, might be odd, but maybe there are other situations where this can be actually hard to debug:
#include <utility>
struct Type {
constexpr bool operator == (int i) {
return i==102;
}
};
template <typename X>
constexpr void f1(X Type) {
// does not fail because lambda is called which returns 101
static_assert(Type() == 101, "");
}
void f2() {
// fails because the operator == checks against 102
static_assert(Type() == 101, "");
}
int main() {
f1([] { return 101; });
f2();
return 0;
}
Here is probably a better example, maybe still an odd one but I could imagine that this one is more likely to occur:
bar(TypeA()); would not construct TypeA directly but TypeA operator () is called on the object of type TypeB:
#include <utility>
struct TypeA {
void operator () () {
}
};
struct TypeB {
TypeA operator () () {
return TypeA();
}
};
void bar(TypeA a) {
}
void foo(TypeB TypeA ) {
bar(TypeA());
}
int main() {
foo(TypeB());
}

When is definition of class' static data member (un/-)necesary

I have a big project and work on refactoring it. Major task is rewrite of logger. New logger is (as far as I can tell) API-compatible with old one, so I believed that after changing header include directory, recompile and relink everything should work. But no. I get multiple errors of the kind undefined reference to <static_data_member>. I can't paste actual code, but it looks for example like this:
// Foo.h
class Foo {
static const int bar = 0;
int baz; // assigned in c-tor
void updateBaz() { baz = bar; }
// ....
}
static const int bar is NOT defined in Foo.cpp. It is sometimes printed by log macros. And it used to work (with old logger), now I have to define it. What change could have caused it?
Another example that that occurs with variables declared by boost:
(...)/blog_adaptor.h:50: error: undefined reference to bbost::serialization::version<CA::CReyzinSignature>::value'
So: when are definitions to static members required and when can they be omitted?
Unless the variables are declared inline (a C++17 feature), definitions of static member variables are not optional, as far as the C++ standard is concerned. Failure to provide a definition is undefined behavior.
Compilers and linkers may vary on exactly what will make them check to see if definitions exist, but that is the nature of undefined behavior.
As Nicol Bolas answered, the code in my project had undefined behavior because static data members were initialized but nowhere defined. To summarize and extend:
Static data member doesn't need to be defined when:
It is not used or is used only in discarded branches (non-instantiated templates and discarded branches of constexpr-if)
in C++17 if member is inline
also clang-tidy says that "out-of-line definition of constexpr static data member is redundant in C++17 and is deprecated", so probably static constexpr also doesn't need it
Further, following code shows why my bad project was not triggering linker error before. I don't know whether it is "not odr-use" or "Undefined Behavior that doesn't hurt you yet":
#include <boost/serialization/version.hpp>
class Klass {};
//BOOST_CLASS_VERSION(Klass, 3);
// would be expanded to:
namespace boost { namespace serialization {
template<>
struct version<Klass> {
static const int value = 3; // not defined anywhere
};
} }
int foo (int val) { // was used by old logger
return val;
}
int bar (const int &val) { // is used by new logger
return val;
}
int main () {
// return bar(boost::serialization::version<Klass>::value); // link error
return foo(boost::serialization::version<Klass>::value); // works fine
}
So there is no link error if member is used but not it's address is not queried. Passing value by reference qualifies as querying the address.

Functions with C linkage able to return class type?

I observed a function in a dll which has C linkage. This function returns class type. I am not sure how this is made possible as C doesn't understand class.
I wrote a sample dll and program myself and noted that the VC++ compiler shows a warning to this effect but doesn't stop you. The program is able to GetProcAddress of this function and call it to receive the returned object. The class definition was made available to program.
Furthermore, if I write a function with C linkage that returns a class type where this class is not even exported, the compiler doesn't issue any warning. The program can consume this function from the dll provided the class definition is made available to it.
Any thoughts on how this works? Is such a behavior compiler/platform specific?
You are misunderstanding the behavior of extern "C".
It only impacts the name of the function in the object file by preventing name mangling. It does not make a function neither "more C" or "less C++". The only additional limitation which extern "C" adds to a C++ function is that is shall not be overloaded.
It's possible for functions with C linkage to return objects that can't be expressed in C so long as they can be manipulated in C. According to my copy of Design & Evolution of C++ (section 11.3.3):
We considered several alternatives to the type-safe linkage schemes before deciding on the one actually added to the language [Stroustrup,1988]: ...
provide type-safe linkage only for functions that couldn't be C functions because they had types that couldn't be expressed in C. ...
A function declared to have C linkage still has C++ calling semantics. That is, the formal arguments must be declared, and the actual arguments must match under the C++ matching and ambiguity control rules. ... Had we provided special services for C, we would have been obliged to add an unbounded set of language calling conventions to C++ compilers [for linking to Pascal, Fortran, PL/I, etc.]. ...
Linkage, inter-language calls, and inter-language object passing are inherently difficult problems and have many implementation-dependent aspects. ... I expect we haven't heard the last of this matter.
That is, C++ linkage isn't based on whether the types involved are valid C types. That is an intentional design decision. It allows you to create a DLL compiled in C++ but that can be used from C via a 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. These all require the C++ runtime. Therefore, the implementation file must be compiled with C++, but since the functions have C linkage, the header can be used from either C or C++.
So how do you get a Foo in C? In this case, you don't, because there's no way to fully declare it in the header in a way that C will understand. Instead, C only sees the forward declaration, which creates an incomplete type. C doesn't know how large an incomplete type is, so C functions can't create it or operate on them directly, but C does know how large a pointer to an incomplete type is, so C can operate on a pointer to an incomplete type. You can get much more creative and actually create POD types in C++ that you can operate on directly in C.
As long as you only use Foo*s in C, you don't have to actually define the Foo struct in C. It so happens that APR uses a similar design ("Creating an APR Type," I couldn't find a better link).
A class object is basically just a struct object, with some extra "hidden" members for the vtbl and so on.
However, I'm not sure what you mean by "the program can consume this function provided the class definition is made available to it". C would throw a compiler error on seeing class Blah { ... };.

Nested functions are not allowed but why nested function prototypes are allowed? [C++]

I was reading the linked question which leads me to ask this question.
Consider the following code
int main()
{
string SomeString();
}
All says, compiler takes this as a function prototype and not as a string object. Now consider the following code.
int main()
{
string Some()
{
return "";
}
}
Compiler said this is invalid as I guess nested function definition is not allowed. If it is not allowed, why nested function prototypes are allowed? It is not giving any advantage rather than making confusion (or am I missing some valid points here?).
I figured out the following is valid.
int main()
{
string SomeFun();
SomeFun();
return 0;
}
string SomeFun()
{
std::cout << "WOW this is unexpected" << std::endl;
}
This is also confusing. I was expecting the function SomeFun() will have a scope only in main. But I was wrong. Why compiler is allowing to compile code like the above? Is there any real time situations where code like the above makes sense?
Any thoughts?
Your prototype is just 'Forward Declaration'. Please check out the Wikipedia article.
Basically, it tells the compiler "don't be alarmed if the label 'SomeFun' is used in this way". But your linker is what's responsible for finding the correct function body.
You can actually declare a bogus prototype, e.g. 'char SomeFun()' and use it all over your main. You will only get an error when your linker tries to find the body of your bogus function. But your compiler will be cool with it.
There are lots of benefits. You have to remember the function body is not always in the same source code file. It can be in a linked library.Also, that linked library may be have a specific 'link signature'.Use conditional defines you may even select the correct link signature at build time using your scoped prototypes.Although most people would use function pointers for that instead.
Hope this helps.
Just as a side note, C++03 does have a roundabout way of defining local functions. It requires abusing the local-class feature:
int main()
{
struct Local
{
static string Some()
{
return "";
}
};
std::cout << Local::Some() << std::endl;
}
This is a convention from C -- like many -- which C++ has adopted.
The ability to declare a function inside another function in C is a decision that most programmers probably consider regrettable and unnecessary. Particularly with modern OOP design where function definitions are comparatively smaller than they are in C.
If you would like to have functions that only exist in the scope of another function, two options are boost::lambda and C++1x lambda.
As to why your declaration of
void f() {
void g(); g();
}
is better than this one
void g();
void f() {
g();
}
It's generally good if you keep declarations as local as possible, so that as few name clashes as possible result. I say it's arguable whether declaring a function locally (this way) is really fortunate, as i think it's still better to ordinary include its header and then go the "usual" way, which is also less confusing to people not knowing about that. Sometimes, it's also useful to work around a shadowed function
void f() {
int g;
// oops, ::g is shadowed. But we can work around that
{
void g(); g();
}
}
Of course, in C++ we could call function g using its_namespace::g() - but in the old days of C, that wouldn't have been possible, and that thing allowed the programmer to still access the function. Also note that while syntactically it is not the same, semantically the following does also declare a function within a local scope, that actually targets a different scope.
int main() {
using std::exit;
exit();
}
As a side note, there are more situations like that where the target scope of a declaration is not the scope where that declaration appears in. In general, the entity you declare becomes a member of the scope in which the declaration appears. But that's not always the case. Consider for example friend declarations, where that thing happens
struct X { friend void f() { std::cout << "WoW"; } };
int main() { void f(); f(); } // works!
Even though the function declaration (and definition!) of f happened within the scope of X, the entity (the function itself) became a member of the enclosing namespace.
Function prototypes are hints for the compiler. They indicate that the functions are implemented somewhere else, if not already discovered. Nothing more.
When you declare a prototype as you are doing you are basically telling the compiler to wait for the linker to resolve it. Depending where you write the prototype the scoping rules apply. There is nothing technically wrong writing the prototype inside your main() function (although IMHO a bit messier), it just means that the function is only locally known inside the main(). If you would have declared the prototype at the top of your source file (or more commonly in a header file), the prototype/function would be known in the whole source.
string foo()
{
string ret = someString(); // Error
return ret;
}
int main(int argc,char**argv)
{
string someString();
string s = somestring(); // OK
...
}