I want to write a C-wrapper around an existing C++ codebase. So I need to implement some C-API functions that merely forward their operations to the corresponding C++ methods.
My problem is, I cannot figure out how to implement a forward-defined struct by means of an existing class:
//Foo.hpp
namespace myLib {
struct Foo {
//some meaningful C++ body
};
}
//foo.h
//#ifdef __cplusplus etc. left out
extern "C" {
struct myLib_foo;
myLib_foo* mkfoo();
//etc.
}
//foo.cpp
extern "C" {
#include "Foo.hpp"
#include "foo.h"
typedef myLib_foo myLib::Foo; //this does not work
myLib_foo* mkfoo() { return new myLib::Foo(); }
}
In this situation, the C-API can and shall only work with pointers to myLib::Foo, which obviously works well, if I define myLib_foo as a new struct inside foo.cpp. I guess it also works, if I define a struct myLib_foo somewhere else. Yet, since I want to keep my namespaces manageable, I am searching a way to define myLib_foo to be equivalent to some existing (and completely defined) struct. This, however does not work, since my compiler refuses the code above with "typedef redefinition with different types". Apparently, it distinguishes between type-aliases and structs.
Is there even a way to achieve what I want or does C++ have no means for real type-aliases?
edit:
By the answer below, I figured I can use inheritance plus static_cast:
//foo.cpp
extern "C" {
#include "Foo.hpp"
#include "foo.h"
struct myLib_foo : public myLib::Foo {}; //this does work
myLib_foo* mkfoo() { return static_cast<myLib_foo*>(new myLib::Foo()); }
}
The C code does not ever need a definition of the struct myLib_foo that it sees.
It handles it only through pointers and functions.
On the C++ side a simple implementation is a struct containing a pointer to the "real" object that it represents. You then define it in the ordinary way (in the C++ code), but of course with the name already established for the C code usage.
If you want to avoid even that little inefficiency, to hand out real object pointers to the C code, well then you have essentially two options:
reinterpret_cast, or
static_cast with the not-quite-C struct as a (possibly empty) base class.
But I would go for the simple implementation of myLib_foo as a struct with a pointer to the real one. The KISS principle: Keep It Simple, Stupid*. On second thoughts, to avoid allocation and deallocation issues, and to also avoid a formal dependency on the compiler (even if that would just be academic, a formality), I would go for the static_cast. For thinking about what it all entails, this seems simplest.
*: Oh, the last few times I mentioned this principle on SO, those answers were heavily downvoted. That has also happened when I have (correctly) proposed macros as solutions. I think one should be technically honest and ignore the general SO readership, so I mention it anyway.
Related
All the solutions to circular include dependencies I've seen just say in "this particular case" the full class definition isn't necessary since "you" are only using pointers to that class.
I encountered this problem and fixed it using forward declarations.
I am wondering what are you supposed to do when you need the specific definition of the other class in both classes.
Also, why does using a pointer to the class allow you use a forward declaration instead of a class definition?
In what cases would you need the specification known beforehand for both classes?
One impossible case is the following:
class A
{
B m_b;
};
class B
{
A m_a;
};
But this is impossible since the size of class A depends on the size of class B, but the size of class B depends on the size of class A. You'll also get an infinite series A myA; myA.m_b.m_a.m_b.m_a.... when you try to construct either.
If you use pointers, you don't need to know the size of either; a pointer is always the same size depending on the platform your are on. And the series disappears because objects in the heap need to be created explicitly.
I am wondering what are you supposed to do when you need the specific
definition of the other class in both classes.
It can be done with forward declarations and deferred definitions in modern compilers. Many older compilers only allow pointers & references to forward declared types.
Here's a contrived example:
A.hpp
class B;
class A
{
public:
int32_t Value;
A(int32_t value) : Value(value) { }
int32_t Add(B b) const;
}
B.hpp
#include "A.hpp"
class B
{
public:
int32_t Value;
B(int32_t value) : Value(value) { }
int32_t Sub(A a) const;
}
AB.hpp
#include "A.hpp"
#include "B.hpp"
inline int32_t A::Add(B b) const
{
return this->Value + b.Value;
}
inline int32_t B::Sub(A a) const
{
return this->Value - a.Value;
}
Also, why does using a pointer to the class allow you use a forward
declaration instead of a class definition?
Forward declarations are just names to the compiler. The concept exists so you can use types that haven't been defined yet. This is necessary because of the way C++ parses code, an artifact of the C language it inherits a great deal from. C++ parsers are really just forward-only text processors that inject text when you #include and use macros. It's a conceptually simple model that made C/C++ compilers easier to write in the early days. Contrast this to C#/Java where you just use using/import and happily create circular dependencies between classes with simple syntax.
Pointers are really just integers, similar to short and int, but with special semantics enforced by the language and a fixed size known at compile time based on the CPU architecture. This makes pointer declarations very simple for compilers to deal with.
Forward declaration facilitates circular dependencies and implementation hiding(which also happens to speed up compilation time). Consider the pimpl idiom. Without forward declarations there's no type-safe way to hide implementation details.
Is it legal to forward-declare a struct as a C-struct
// api.h
#ifdef __cplusplus
extern "C" {
#endif
typedef struct handle_tag handle_t;
handle_t *construct();
void destruct(handle_t *h);
void func(handle_t *h);
#ifdef __cplusplus
}
#endif
and subsequently define it as a C++-struct, i.e. as a non-POD type?
// api.cpp
struct handle_tag {
void func();
std::string member;
};
void func(handle_t *h) {
h->func();
}
The general intention is to get via a C interface an externally accessible opaque type handle_t which is internally implemented as an C++ data type.
Yes, that will work fine as long as the C code never needs to see "inside" the handle_tag structure, and the appropriate C++ construction/destruction is performed by the C++ code (which I preseume the construct and destruct are for).
All that the C code needs is a pointer to some datastructure - it won't know what the contents is, so the content can be anything you like it to to be, including constructor/destructor reliant data.
Edit:
I should point out that this, or methods similar to it (e.g. using a void * to record the address of an object for the C portion to hold), is a fairly common way to interface C-code to C++ functionality.
Edit2:
It is critical that the C++ code called doesn't "leak" exceptions into the C code. That is undefined behaviour, and very much liable to cause crashes, or worse, "weird things" that don't crash... So unless the code is guaranteed to not cause exceptions (and for example std::string is liable to throw bad_alloc in case of low memory), it is required to use a try/catch block inside code like construct anf func in the C++ side.
Won't work quite as is, but the concept's ok. When the functions are defined, you also need to make sure the names aren't mangled so that the C code can find them. That means #include "api.h" should be added atop your api.cpp file.
I want to exclude some headers from my include chain after having used them. From what I know there is no exclude "header.h" in c++11.
Pseudo Code Wishful thinking:
#include "the_bad_header.h" //long includechain with later unused declarations
class bulky { ... };
constexpr std::size_t bulkysize = sizeof(bulky);
forget everything included and class bulky and remember only bulkysize
My example where the problem becomes evident follows. Please don't argue this is not a serious problem. The Example is broken down to show the minimal abstract language usage. I will describe the old fashioned solutions and their disadvantages too.
Old style solution
justanotherheader.h:
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
};
justanothercppunit.cpp:
#include "justanotherheader.h"
#include "boost/lotsofheaders.hpp"
//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
bulkywrap::bulkywrap()
: pImpl( new bulkywrap_pImpl() )
{}
My current Solution
justanotherheader.h:
#include "stdint.h" // this is the only header I like to use, but also unnecessary.
#define UNKNOWNSIZE 12345
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
uint8_t pImpl_Placement[UNKNOWNSIZE]; //placement new for pImpl
};
justanothercppunit.cpp:
#include "justanotherheader.h"
#include "boost/lotsofheaders.hpp"
//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
bulkywrap::bulkywrap()
: pImpl( new(this->pImpl_Placement) bulkywrap_pImpl() ) //using this here is safe
{}
So, the code above is working. The advantages are: hiding complexity and having no runtime dynamic memory indirections. Huh? I mean, the placement new allows the whole object to be put on stack and all member addresses are known at compile time. My attempt is to have best performance while using interface design of opaque pointer.
If you think: "this performance advantage is not worth the thinking effort." then please leave that question.
My expected Solution
justanotherheader.h:
#include "stdint.h" // this is the only header I like to use, but also unnecessary.
constexpr std::size_t get_bulkywrap_pImpl_Size( void ); //constexpr function forward declaration
extern constexpr std::size_t bulkywrap_pImpl_Size; //constexpr literal forward declaration with external initialization
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
uint8_t pImpl_Placement[get_bulkywrap_pImpl_Size()]; //undefined constexpr used
uint8_t pImpl_Placement[bulkywrap_pImpl_Size]; //alternative to above. undefined constexpr used
};
justanothercppunit.cpp:
#include "justanotherheader.h"
#include "boost/lotsofheaders.hpp"
//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
constexpr std::size_t get_bulkywrap_pImpl_Size( void )
{
return sizeof(bulkywrap_pImpl);
}
constexpr std::size_t bulkywrap_pImpl_Size = sizeof(bulkywrap_pImpl);
bulkywrap::bulkywrap()
: pImpl( new(this->pImpl_Placement) bulkywrap_pImpl() ) //using this here is safe
{}
In my current solution I need to verify the sizeof(bulkywrap_pImpl) and adjusting UNKNOWNSIZE manually.
I think it is currently not possible to get any information from a compilationunit to others. I know this is typically intended by good reason, but this limits the possibilities of c++11.
I want to point out:
jtc1 sc22 wg21 paper n3337
jtc1 sc22 wg21 paper n3308
Please help me to find information weather and why the standard does not allow this.
But furthermore I would like to find a solution of how to export some literal constant during compiliation time out of a compileunit into another compileunit. It's just a literal, so all statements and expressions are not affected by it. Thus compilation does not depend where the size of the array comes from.
My suggestion results in some work for the ISO-jtc1-sc22-wg21 and the compiler developers, but I don't see any relevant difference between template and constexpr since every definition must appear in the same translationunit. This makes modular programming and clean interfaces bogus.
And no: I don't want to use preprocessor macros, dynamic new or virtual member functions. Of importance is maximal const-correctness, since the size of the class is const.
Please help
you can't have both "compile-time" and "from another compilation unit" at the same time. also it's not clear why do you need to forget successfully parsed header. parsing time already consumed. i suggest you to create another header with size constant, include it from both files, and add static_assert to pimpl file, checking that constant >= sizeof(pimpl). you can generate this header as part of your build system by compiling source file including pimpl and doing cout <<sizeof(pimpl). also i suggest you to not waste time and space for pimpl pointer and replace it with member function, returning address of properly cast buffer. also you failed to show where you call pimpl's destructor. also implementing assignment/copy/move/swap will be a lot of fun
use static_assert in cpp to check that size declared in header >= size of impl class
I have used forward declarations a lot; they help avoid many #includes, improve compilation time and what not. But what if i want to forward-declare a class in the standard library?
// Prototype of my function - i don't want to include <vector> to declare it!
int DoStuff(const std::vector<int>& thingies);
I have heard it's forbidden/impossible to forward-declare std::vector. Now this answer to an unrelated question suggests to rewrite my code this way:
stuff.h
class VectorOfNumbers; // this class acts like std::vector<int>
int DoStuff(const VectorOfNumbers& thingies);
stuff.cpp
// Implementation, in some other file
#include <vector>
class VectorOfNumbers: public std::vector<int>
{
// Define the constructors - annoying in C++03, easy in C++11
};
int DoStuff(const VectorOfNumbers& thingies)
{
...
}
Now, if i use VectorOfNumbers instead of std::vector<int> in all contexts throughout my project, everything is going to be good, and i don't need to #include <vector> in my header files anymore!
Does this technique have major disadvantages? Can the gain of being able to forward-declare vector outweigh them?
If you ever delete a VectorOfNumbers as a std::vector<int> (and since you used public inheritance this conversion is implicit) you've entered the realm of undefined behavior. This is probably more likely to accidentally happen than one might suspect.
I've never personally noticed significant compilation slowdown from just including vector where needed, but if you really want to isolate the include, use a client API interface that doesn't know about the underlying container type (vector) and pimpl the vector include into a single source file.
The reason I wouldn't do this:
const std::vector<int>& a = a_3rd_party_lib::get_data(); // this type is out of your control
DoStuff(a); // you cannot pass it to this function!
You include <vector> in your header file. The <vector> header will have been built to prevent multiple inclusions, so you just include it everywhere you need it.
This works well for the interface for a class, but not for the implementation. If your class has any vector members you must #include <vector> or the class definition will not compile.
Instead of inheritance, you could use composition:
// Implementation, in some other file
#include <vector>
class VectorOfNumbers
{
public:
std::vector<int>& container;
VectorOfNumbers(std::vector<int>& in_container)
: container(in_container)
{
}
};
int DoStuff(const VectorOfNumbers& thingies)
{
std::sort(thingies.container.begin(), thingies.container.end());
// ...
}
The downside is the extra variable name on every access.
Also, you'd need this implementation to be in a header file included by cpps so they will know what they can do with VectorOfNumbers.
Essentially, just making a wrapper for your vector. This is like a light-weight version of PImpl (we only care about avoiding header dependencies so we don't need the full pointer decoupling). It avoids the issues raised by Mark B and ybungalobill.
But I don't think it's really worth it.
If I have a class in outside.h like:
class Outside
{
public:
Outside(int count);
GetCount();
}
How can I use it in framework.cpp using the extern keyword, where I need to instantiate the class and call GetCount?
Edit:
#include is not allowed.
Everyone here is a bit too gentle.
There is ABSOLUTELY NO REASON why you would not want to include the .h file.
Go for it and include the file!
Just to clarify. It is impossible to extern the class:
class Outside
{
public:
Outside(int count);
GetCount();
}
But, once you have the class available in framework.cpp, you CAN extern an object of type Outside. You'll need a .cpp file declaring that variable:
#include "outside.h"
Outside outside(5);
And then you can refer to that object in another file via extern (as long as you link in the correct object file when you compile your project):
#include "outside.h"
extern Outside outside;
int current_count = outside.GetCount();
extern is used to say "I KNOW a variable of this type with this name will exist when this program runs, and I want to use it." It works with variables/objects, not classes, structs, unions, typedefs, etc. It's not much different from static objects.
You may be thinking about forward declaring classes to cut down on compile times, but there are restrictions on that (you only get to use the objects as opaque pointers and are not able to call methods on them).
You may also mean to hide the implementation of Outside from users. In order to do that, you're going to want to read up on the PIMPL pattern.
Update
One possibility would be to add a free function to Outside.h (I've also added a namespace):
namespace X {
class Outside {
int count_;
public:
Outside(int count) : count_(count) { }
int GetCount()
{
return count_;
}
};
int GetOutsideCount(Outside* o);
}
Implement that function in a .cpp file. While you're at it, you might as well make the global variable that you intend to extern (note, the variable itself does not need to be a pointer):
#include "outside.h"
namespace X {
int GetOutsideCount(Outside* o)
{
return o->GetCount();
}
}
X::Outside outside(5);
And then do this in your program (note that you cannot call any methods on outside because you did not include outside.h and you don't want to violate the one definition rule by adding a new definition of the class or those methods; but since the definitions are unavailable you'll need to pass pointers to outside around and not outside itself):
namespace X {
class Outside;
int GetOutsideCount(Outside* o);
}
extern X::Outside outside;
int main()
{
int current_count = GetOutsideCount(&outside);
}
I consider this an abomination, to put it mildly. Your program will find the GetOutsideCount function, call it by passing it an Outside*. Outside::GetCount is actually compiled to a normal function that takes a secret Outside object (inside Outside::GetCount that object is referred to via the this pointer), so GetOutsideCount will find that function, and tell it to dereference the Outside* that was passed to GetOutsideCount. I think that's called "going the long way 'round."
But it is what it is.
If you aren't married to using the extern keyword, you can instead go full "let's use C++ like it's C" mode by adding the following two functions in the same way (i.e., via forward declarations and implementing right next to int GetOUtsideCount():
Outside* CreateOutsidePointer(int count)
{
return new Outside(count);
}
void DestroyOutsidePointer(Outside* o)
{
return delete o;
}
I'm more willing to swallow that. It's a lot like the strategy used by the APR.
You don't make classes extern. Just include "outside.h" and create an instance of Outside.
you cant extern the class, but you can extern a function that creates an instance.. In the consumer code:
class Outside;
extern Outside* MakeAnOutside(int count);
extern int GetOutsideCount(Outside* outside);
Then in outside.h:
Outside* MakeAnOutside(int count)
{
return new Outside(count);
}
int GetOutsideCount(Outside* outside)
{
return outside->GetCount();
}
but.. this may not be a good idea..
Include files are for definitions, including class definitions. extern is for variables.
If you don't have the definition of a class in a source file, about the only thing you can do with it is declare it with class Outside; and pass instances around by pointer. You can't actually do anything with the instances, including construction, destruction, or calling member functions like GetCount(). For this, you don't need extern at all; only if you want to refer to a variable in another source file, and that won't let you do anything additional with it.
There is no valid reason not to use #include here. The only alternative is to copy-and-paste the header file into the source file, and that's considerably worse. Anybody who tells you not to use #include does not understand C++, and obviously anybody who thinks extern has any relevance here certainly doesn't.
If at all possible, you should get an experienced C++ developer to help you learn, establish good coding styles, and mentor you in how to develop C++. I suspect you're doing other things that will turn out to be Bad Ideas later on.
If you had a silly requirement that #include is not allowed then you'd have to copy and paste the class declaration into your .cpp file. Need I say that'd be a very bad idea?
What is the reason for this requirement? It pains me to advise you how to do this. If you are trying to avoid long #include paths in your source files, this is a build problem not a source code problem.
You should add directories to the include path with the gcc -I option, or whatever the equivalent is for your compiler.
If you are really, really sure about this, you'd want something like this:
framework.cpp
// FIXME: Should #include "outside.h" but not allowed.
class Outside
{
public:
Outside(int count);
GetCount();
// Omitted
// void SomeUnusedMethod();
};
<code for framework.cpp here>
void UseOutside()
{
Outside o(5);
std::cout << o.GetCount() << std::endl;
}
I would then strongly recommend you leave the declaration as is so it's just straight copy-and-pasted from the header file. But if you want to trim it you can omit any non-virtual methods you don't use. You'll need to keep all variables.
I can only think of one use case where you could 'extern' a class without either #including the header or duplicating the class definition as others have suggested.
If you need to keep pointer to the class but you never dereference it directly, only pass it around, then you can do the following in your file:
class Outside;
class MyClass
{
Outside* pOutside;
void SetOutsidePointer(Outside *p) {pOutside = p;}
Outside* GetOutsidePointer() { return pOutside;}
/* the rest of the stuff */
}
This will only work if you never call pOutside->GetCount() or new Outside in your file.
Put the include for your Outside class in the StdAfx.h or any other headerfile that framework.cpp is already including.
I think you misunderstand the storage classes and one of them is the external.
"Objects and variables declared as extern declare an object that is defined in another translation unit or in an enclosing scope as having external linkage."
So marking extern is for variables not classes defination/declaration
So if you can not include the .h, I recommend you to build the .h and .cpp to be static lib or dll and use in your code
Yikes... we put classes in header files and use #include in order to duplicate class (or other) declarations into multiple cpp files (called compilation units).
If you really can't use #include, you're left with a manual copy, as suggested above, which has the obvious problem of becoming outdated when someone changes the original. That'll completely break your test code with hard to track crashes.
If you insist on going down the path of this manual copy, you do need the entire class declaration. Technically, you could omit certain bits and pieces, but this is a bad idea -- clearly your team doesn't have deep understanding of C++ constructs, so you're likely to make a mistake. Second, the C++ object model is not standardized across compilers. Theoretically even a simple non-virtual method could change the model, breaking your test.
A "long path" is really not a great reason not to include a file directly. But if you really can't, copy the entire header file in where #include would have been -- that's exactly what the C preprocessor is going to do anyway.