So I'm working on an Modular C++ library for me and my team. Here is my situation:
I have a library A which contains a complex storage control class a. I have also a library B that is something like a interface to an complex protocol which contains an special response. Now, I want to have a function in class a, which CAN use B. This can be helpful for Program X, which uses A and B. But there is also Program Y, which will only use A and not the complex library B.
How can I get this behavior in C++? Do I need macros, symbols or is there an other way to implement this easily so that I don't need to include an extra file in a Program? Which type of library is the better one?
This is pretty common in system libraries, where optional features can be chosen at (library) compile time. With this approach, you would have one or more #define preprocessor macros guarding the optional features. Thus, in library A:
#ifdef USE_LIBRARY_B
#include <b/foo.h>
int A_optional_feature_using_B(void) { ... }
#endif
// rest of library A follows
At compile time you would either define USE_LIBRARY_B or not (and add any necessary linker flags of course). For example, with gcc on a UNIX-like platform:
$ gcc ... -DUSE_LIBRARY_B ...
Most commonly, something like autoconf is used for UNIX environments to give the end-user an easy way to select the optional features. Thus, you might see:
me#pc:library_a$ ./configure --with-library-b
See the autoconf documentation for information on how to set something like that up.
On Windows, you could do something similar (e.g., in Visual Studio, use different Project/Solution configurations that define the appropriate macros).
The above gives you compile-time only control over the extra features. To allow the choice to be made at runtime so that the library can use B if present, you will need to use runtime dynamic linking. This is highly platform-specific. On Linux, use libdl. On Windows, use LoadLibrary() and friends. Here you will have to do a lot of extra coding to look for and load the optional library if present and to return appropriate error codes / exceptions if not present and functions requiring the optional library are called.
If all this sounds like a pain in the rear, you're right, it is. If there is any reasonable way to adjust your strategy so that you don't have to do this, you will be better off. But for some use cases this is necessary and appropriate and if yours is so, then I hope the above gives you some starting points, and good luck.
Related
I'm currently ending the development of a C++ header-only template library for grid-based quantum computations and I'm considering replacing an old logging module that I've wrote nearly at the beginning.
I know that it sounds a little bit weird to have a header-only library printing stuff to stdout (and files), but I make heavy use of templates to increase flexibility and efficiency of the runtime binary, hence this choice.
The current logging module uses printf (as I disliked std::cout syntax), macros, variadic macros (##__VA_ARGS__), supports console colors and prints out the the location in the source using __FILE__, __LINE__ macros, i.e. nothing modern nor type safe, but it works.
Does it make sense replace it with fmt (or something similar) or should I rather try to modernize the existing one (i.e. replace variadic macros with templates, custom built compile-time string_view's etc.)?
I'd like the library to work "straight-away" that is, I'd like to either:
a) eliminate as much dependencies as possible
b) try find_package(fmt) or FetchContent them silently in CMake - (btw. is there a general CMake "template" for this behaviour? something like "find_or_fetch"? )
c) place the essential part of fmt as a git submodule in my project and include a small header file.
Beside this, I'm also planning to use HDF5 library (with or without C++ wrappers).
Here again I'm not sure how to best approach it to make the integration as seamless as possible, neither have I decided which wrapper should I use.
Would a "find_or_fetch" paradigm be appropriate for header-only library?
It makes sense if you do a lot of formatting and {fmt} is designed to support easy embedding. In particular, it has zero dependencies and is relatively small with the minimal configuration consisting of just three moderate-size files. There are several projects that embed {fmt}, for example, spdlog. The advantage compared to rolling out your own formatting solution is that it will be easy to port to std::format in the future.
I wouldn't if I were you.
A header-only library implies being minimalistic. fmt is the opposite of that.
A header-only library implies being user-friendly. Forcing a large dependency on a user isn't very friendly.
If you've gone that far without needing better logging tools, chances are, the tools you are using are already good enough.
Having to match format strings and arguments is one of the largest drawbacks of not using fmt. But you've done that matching already. And modern compilers warn about any mismatches as long as format strings are literals.
Recently, I was learning about networking in C++ and I found boost.asio which is a cross platform library, and then I got a thought about how this library is a cross platform since Windows provides different library for networking and even mac also,
so how its function works on different machines, does cross platform libraries create their own functions for this purpose or they contain different private functions of different machine's logics and provides public functions which then during compiling time check for on which machine that codes are compiling and change our written functions with machines defined libraries.
For example
//Operations for windows
Private void WindowsFunc
{ code }
//Operations for mac
Private void MacFunc
{ code }
//library's functions
Public void Do
{
//Performs different operations
//for different machines
If (windows)
WindowsFunc
else if (Mac)
MacFunc
}
It could be a solution may be😗
There are several possible ways:
Use ifdefs
char* doFoo(void){
#ifdef _WIN32
return "win32";
#elif ...
return ...;
#endif ...
}
The pro is, that it doesn't require much setup.
The con is, that it clutters the code, if you do it too much.
Have different implementations in different directories.
As a folder structure:
root
|---->Other files
|---->windows implementation
| |->foo.c
|---->linux implementation
|->foo.c
|---->macos implementation
|->foo.c
And then you can use some build system, or a custom shell script for selecting things.
(Pseudo code)
if(OS==windows)
compileDirectory(windowsImpl);
else if(OS==linux)
compileDirectory(windowsImpl);
if(OS==macos)
compileDirectory(windowsImpl);
The pro is, that it doesn't clutter the code, allows better adding of new features and some sort of abstraction.
The contra is, that it can be quite tremendeous to setup.
This is often done using compiler-specific macros. For example, the gcc compiler defines the preprocessor symbol
__linux
on Linux. So, C or C++ code can use
#if __linux
to compile Linux-specific code. Nothing in the actual code actually #defines this. This is defined by default, by the Linux version of gcc. Similar preprocessor macros are defined on other platforms support by gcc. Other compilers have similar pre-defined macros. Cross-platform library's sources assemble a collection of these macros they check in order to compile operating system-specific code.
Another, common approach is to explicitly define a library-specific symbol as part of the library's build instruction or script. The build instructions that come with a cross-platform library include the instructions for running the appropriate script, from the library's package, that runs the compiler and explicitly sets the appropriate preprocessor symbol, which is then used in this manner.
Generally, preprocessor usage is discouraged in modern C++ code, and used sparingly. This is one use case where preprocessor macro usage is quite common, in practice.
Generally cross platform libraries are implemented in layers.
There is the public interface, the common code, and a minimalized set of platform dependent code.
The public interface usually uses #if defined(symbol) checks to determine which platform it is running on. It may include system headers based on this, but more often will simply forward declare any symbols it needs to expose for platform specific APIs (if any). In some cases, header only libraries will go further than this.
The common code will have minimal platform specific stuff in it. It will try to deal with platform specific stuff using abstraction; it may #include platform specific helper headers, but the code is common between platforms.
Like, it might use Native::RWLock and Native::RWLock::lock( mutex ) functions that are typedefs and thin wrappers around platform specific types.
The platform specific code is different for each platform. It may be conditionally compiled in the build system NativeMutexImp_mac.cpp , or wrapped in #ifdef blocks, or even both.
Now header only libraries are leakier than this. And some less organized cross platform code will mix thenplatform specific and not code all over the place. Finally, performance requirements may require some leaking platform specific code in public header files.
But the main idea is that you hide the OS API use that you in turn use to implement your cross platform functionality.
This can make the end user code faster than native OS API use if your API makes efficient use easier than the native APIs do. Optimization is fungible; code that is easier to make performant is actually faster in practice.
I am developing a C++ application which is required to load a dynamic library at runtime using dlopen. This library generally won't be written by me.
What method do people recommend to ensure future binary compatibility between this library and my application?
The options as I see them are:
Put the version number in the library file name, and attempt to load it (through a symbolic link) no matter what. If dlopen fails, report an error.
Maintain a second interface which returns an version number. However, if this interface changes for some reason, we run into the same problems as before.
Are there any other options?
You should define a convention about the dynamically loaded (i.e. dlopen-ed) library.
You might have the convention that the library is required to provide a const char mylib_version_str[]; symbol which gives the version of the API etc etc. Of course you could have your own preprocessor tricks to help about this.
For your inspiration, you might look at what GCC requires from its plugins (e.g. the plugin_is_GPL_compatible symbol).
If the dynamically loaded library is in C++, you might use demangling to check the signature of functions....
why not use both options? by istance few libraries already do that (Lua for example, old dll is Lua51.dll, then you have Lua52 etc. nd you can also query its version.)
A good interface can change, but not so often, why should 2 simple static methods
const char* getLibraryName();
uint32 getLibraryVersion();
change overtime?
if you/they are using a libtool to build a library/application you may recommend this way: http://www.gnu.org/software/libtool/manual/libtool.html#Versioning
I'm trying to adjust some mathematical code I've written to allow for arbitrary functions, but I only seem to be able to do so by pre-defining them at compile time, which seems clunky. I'm currently using function pointers, but as far as I can see the same problem would arise with functors. To provide a simplistic example, for forward-difference differentiation the code used is:
double xsquared(double x) {
return x*x;
}
double expx(double x) {
return exp(x);
}
double forward(double x, double h, double (*af)(double)) {
double answer = (af(x+h)-af(x))/h;
return answer;
}
Where either of the first two functions can be passed as the third argument. What I would like to do, however, is pass user input (in valid C++) rather than having to set up the functions beforehand. Any help would be greatly appreciated!
Historically the kind of functionality you're asking for has not been available in C++. The usual workaround is to embed an interpreter for a language other than C++ (Lua and Python for example are specifically designed for being integrated into C/C++ apps to allow scripting of them), or to create a new language specific to your application with your own parser, compiler, etc. However, that's changing.
Clang is a new open source compiler that's having its development by Apple that leverages LLVM. Clang is designed from the ground up to be usable not only as a compiler but also as a C++ library that you can embed into your applications. I haven't tried it myself, but you should be able to do what you want with Clang -- you'd link it as a library and ask it to compile code your users input into the application.
You might try checking out how the ClamAV team already did this, so that new virus definitions can be written in C.
As for other compilers, I know that GCC recently added support for plugins. It maybe possible to leverage that to bridge GCC and your app, but because GCC wasn't designed for being used as a library from the beginning it might be more difficult. I'm not aware of any other compilers that have a similar ability.
As C++ is a fully compiled language, you cannot really transform user input into code unless you write your own compiler or interpreter. But in this example, it can be possible to build a simple interpreter for a Domain Specific Language which would be mathematical formulae. All depends on what you want to do.
You could always take the user's input and run it through your compiler, then executing the resulting binary. This of course would have security risks as they could execute any arbitrary code.
Probably easier is to devise a minimalist language that lets users define simple functions, parsing them in C++ to execute the proper code.
The best solution is to use an embedded language like lua or python for this type of task. See e.g. Selecting An Embedded Language for suggestions.
You may use tiny C compiler as library (libtcc).
It allows you to compile arbitrary code in run-time and load it, but it is only works for C not C++.
Generally the only way is following:
Pass the code to compiler and create shared object or DLL
Load this Shared object or DLL
Use function from this shared object.
C++, unlike some other languages like Perl, isn't capable of doing runtime interpretation of itself.
Your only option here would be to allow the user to compile small shared libraries that could be dynamically-loaded by your application at runtime.
Well, there are two things you can do:
Take full advantage of boost/C++0x lambda's and to define functions at runtime.
If only mathematical formula's are needed, libraries like muParser are designed to turn a string into bytecode, which can be seen as defining a function at runtime.
While it seems like a blow off, there are a lot of people out there who have written equation parsers and interpreters for c++ and c, many commercial, many flawed, and all as different as faces in a crowd. One place to start is the college guys writing infix to postfix translators. Some of these systems use paranthetical grouping followed by putting the items on a stack like you would find in the old HP STL library. I spent 30 seconds and found this one:
http://www.speqmath.com/tutorials/expression_parser_cpp/index.html
possible search string:"gcc 'equation parser' infix to postfix"
I have a recurring problem with a statically linked library I've written (or in some cases, code was accumulated from open sources).
This library, MFC Toolbox Library by name, has a lot of free functions, classes, and so on which support MFC programming, Win32 API programming, as well as the venerable C-library and newer C++ standard library.
In short, this is a working library with tools that apply to my daily work, that I've accumulated over more than a decade, and is indispensable to our products. As such, it has a rich mixture of utilities and augmentations for all of these various technologies, and often internally mixes usage of all of these technologies to create further support.
For example, I have a String Utilities.h and String Utilities.cpp which provide a plethora of string-related free-functions and even a class or two.
And often I find that I have a pair of functions, one that works without need of MFC or its CStrings, and another sibling function that does need these things. For example:
////////////////////////////////////////////////////////////////////////
// Line Terminator Manipulation
////////////////////////////////////////////////////////////////////////
// AnsiToUnix() Convert Mac or PC style string to Unix style string (i.e. no CR/LF or CR only, but rather LF only)
// NOTE: in-place conversion!
TCHAR * AnsiToUnix(TCHAR * pszAnsi, size_t size);
template <typename T, size_t size>
T * AnsiToUnix(T (&pszBuffer)[size]) { return AnsiToUnix(pszBuffer, size); }
inline TCHAR * AnsiToUnix(Toolbox::AutoCStringBuffer & buffer) { return AnsiToUnix(buffer, buffer.size()); }
// UnixToAnsi() Converts a Unix style string to a PC style string (i.e. CR or LF alone -> CR/LF pair)
CString UnixToAnsi(const TCHAR * source);
As you can see, AnsiToUnix doesn't require a CString. Because Unix uses a single Carriage Return as a line terminator, and Windows ANSI strings use CR+LF as a line terminator, I am guaranteed that the resulting string will fit within the original buffer space. But for the reverse conversion, the string is almost guaranteed to grow, adding an extra LF for every occurrence of a CR, and hence it is desirable to use a CString (or perhaps a std::string) to provide for the automatic growth of the string.
This is just one example, and in and of itself, is not too beastly to consider converting from CString to std::string to remove the dependency upon MFC from that portion of the library. However, there are other examples where the dependency is much more subtle, and the work greater to change it. Further, the code is well tested as is. If I go and try to remove all MFC dependencies, I am likely to introduce subtle errors to the code, which would potentially compromise our product, and exacerbate the amount of time needed on this essentially not-strictly-necessary task.
The important thing I wanted to get across is that here we have a set of functions, all very related to one another (ANSI->UNIX, UNIX->ANSI), but where one side uses MFC, and the other only uses character arrays. So, if I am trying to provide a library header that is as reusable as possible, it is desirable to break out the functions which are all dependent on MFC into one header, and those which are not into another, so that it is easier to distribute said files to other projects which do not employ MFC (or whatever technology is in question: e.g. It would be desirable to have all functions which don't require Win32 headers - which are simply augmentations to C++, to have their own header, and etc.).
My question to all of you, is how do you manage these issues - Technology dependency vs. related functions all being in the same place?
How do you break down your libraries - divide things out? What goes with what?
Perhaps it is important to add my motivation: I would like to be able to publish articles and share code with others, but generally speaking, they tend to use portions of the MFC Toolbox Library, which themselves use other parts, creating a deep web of dependencies, and I don't want to burden the reader / programmer / consumer of these articles and code-projects with so much baggage!
I can certainly strip out just the parts needed for a given article or project, but that seems like a time-intensive and pointless endeavor. It would be much more sensible, to my mind, to clean up the library in such a way that I can more easily share things without dragging the entire library with me. i.e. Reorganize it once, rather than having to dig things out each and every time...
Here's another good example:
UINT GetPlatformGDILimit()
{
return CSystemInfo::IsWin9xCore() ? 0x7FFF : 0x7FFFFFFF;
}
GetPlatformGDILimit() is a fairly generic, utilitarian free function. It really doesn't have anything to do with CSystemInfo, other than as a client. So it doesn't belong in "SystemInfo.h". And it is just a single free-function - surely nobody would try to put it in its own header? I have placed it in "Win32Misc.h", which has an assortment of such things - free functions mostly which augment the Win32 API. Yet, this seemingly innocuous function is dependent upon CSystemInfo, which itself uses CStrings and a whole slew of other library functions to make it able to do its job efficiently, or in fewer lines of code, or more robustly, or all of the above.
But if I have a demo project that refers to one or two functions in the Win32Misc.h header, then I get into the bind of needing to either extract just the individual functions that project needs (and everything that those functions depends upon, and everything those entities depend upon, etc.) -- or I have to try to include the Win32Misc.h and its .cpp - which drags even more unwanted overhead with them (just in order for the demo project to compile).
So what rule of thumb do folks use to guide yourselves as to where to draw the line - what goes with what? How to keep C++ libraries from becoming a dependency tree from hell? ;)
Personally I'd break it down on functionality. String manipulation in one library. Integral types in another (except perhaps char put that into the string lib)
I would certainly keep platform dependant stuff away from non platform dependant stuff. Vendor specific stuff away from the non vendor specific. This might require two or even three string libraries.
Perhaps you could use the paradigm "does it require MFC?" anything that requires mfc should be split out. Then move on to "does it require windows" again do some splitting. and so forth...
Without a doubt some projects will require all libraries have to be compiled in VC++ and only run on windows, that's just the way it goes. Other projects will happily compile on linux using just a subset of the libraries and compilable with gcc.
DC
If you use only conformat types in your public interfaces, and keep the interfaces seperated from the implementations, this becomes a non-issue.
Keep in mind that when you introduce a function like this:
std::string ProcessData();
...and put the source code for this in a module separate from the code that will call it (for example, in a DLL), you break the seperate-interface-from-implementation edict. This is because the STL is a source code library, and every compiler that uses your library functions can and will have different implementations and different binary layouts for the utilities you use.
In a very vague answer, KISS is the best policy. However, it seems that the code has come too far and has reached the point of no return. This is unfortunate because what you would want to do is have separate libraries that are autonomous entities, meaning they don't depend on any outside stuff. You create an MFC helper functions library and another library for other helpers or whatever. Then you decide which ones you want and when. All the dependencies are within each library and they are stand-alone.
Then it just becomes a matter of which library to include or not.
Also, using condition includes within header files works well if you want only certain things under certain scenarios. However, I'm still not entirely sure if I have interpreted the problem correctly.