How to detect declaration of class at compile-time? - c++

I'm use some 3-rd party library at my project. After updating to new version of library I'm faced with errors.
One my class have method
virtual RTSPServer::RTSPClientSession* createNewClientSession(u_int32_t sessionId)override;
but in new version of library declaration of RTSPClientSession was moved into another class and renamed. Now correct name is
GenericMediaServer::ClientSession
I need a code which will be correctly compiles with all versions of library.
At gcc I use following code:
#ifdef RTSPServer::RTSPClientSession
using ClientSessionClass = RTSPServer::RTSPClientSession;
#else
using ClientSessionClass = GenericMediaServer::ClientSession;
#endif
class A
{
.........
virtual ClientSessionClass* createNewClientSession(u_int32_t sessionId)override;
};
but this not work in MSVC 2010.
How I can detect which declaration I should use?
UPD: code for gcc also don't work for old version of library :(

"How I can detect which declaration I should use?"
You need to introduce some discriminator for the library version you're using with your current build configuration:
#ifdef OLD_LIBRARY_VERSION // Maybe the binding headers have some information like this.
// If not you have to select this manually, and provide the
// setting with your project configuration.
using ClientSessionClass = RTSPServer::RTSPClientSession;
#else
using ClientSessionClass = GenericMediaServer::ClientSession;
#endif

Related

Bug in Xcode 7 about precompiled header and forward declaration in C++

I found a bug in latest Xcode 7.0 that annoys us very much in our company because it makes most of our C++ code not debuggable. After lots of experiment, I was able to reproduce it with a minimum amount of code.
In some cases, it is impossible to see members inside a C++ class on LLDB. It seems that three conditions must be present for that bug to appear:
the class is forward declared
the class has a virtual method
the class is declared inside a precompiled header
I am asking whether somebody else already knowns about that bug and what is the recommended procedure to report that bug (to LLVM or Apple ?).
Steps to reproduce:
Create two source files with their content:
header.h
#ifndef HEADER_INCLUDED
#define HEADER_INCLUDED
class A; // forward declaration, has an effect on bug
class A
{
public :
virtual ~A() {}
protected:
int doYouSeeMe;
};
#endif
PCHAndFDbug.cpp
#include "header.h"
int main()
{
A* a = new A();
return 0;
}
Create a small Xcode 7 project with these two files. header.h must be set as a precompiled header (Prefix header setting in Xcode). As a reference, I am using Premake to generate that project and here is the premake5.lua source:
solution "PCHAndFDbug"
configurations {"Debug"}
xcodebuildsettings { MACOSX_DEPLOYMENT_TARGET = "10.7" }
project "WithPCH"
language "C++"
files {"PCHAndFDbug.cpp", "header.h"}
kind "ConsoleApp"
pchheader "header.h"
project "WithoutPCH"
language "C++"
files {"PCHAndFDbug.cpp", "header.h"}
kind "ConsoleApp"
Place a breakpoint on the return 0 statement. Check if you can see member doYouSeeMe in a variable.
Same issue for me. Fixed by turning off "Enable Clang Module Debugging" in the Build Settings
For Apple at least, you should submit a bug report through the developer centre https://developer.apple.com/bug-reporting/
I've encountered this bug too and it is annoying.

boost.future causing problems with clr

I am using visual studio 2012 with a clr library that needs to link to a native library.
My library which is using boost::future.
I am having this problem when I use future::then(F &&) function against the managed project:
Error 910 error LNK2022: metadata operation failed (8013119F) : A TypeRef exists which should, but does not, have a corresponding TypeDef: (dummy): (0x0100003e). D:\ClrProject\somefile.obj
I tried, as suggested in other questions, to make the dummy types in the library complete, since I cannot forward declare a nested struct from inside a template, as can be done with boost::thread::dummy struct.
This did not solve the problem.
My setup is the following:
Boost 1.55.
Using boost .dlls.
define BOOST_RESULT_OF_USE_DECLTYPE
define BOOST_THREAD_PROVIDES_FUTURE
define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
I am using these very defines on the dependent .dll as well, to make sure that all parts of the API are exposed correctly.
Solved.
#Hans Passant your suggestion was right. I just wasn't putting the #pragma the correct way.
I had to put the pragmas so that my headers are compiled as unmanaged code. Once that was done, it seems that template instantiations for my code were emitted as unmanaged. At that point, problems disappeared.
So what I did is something like this:
#pragma managed(push, off)
#include "MyHeaderWithFutures.h"
#pragma managed(pop)
void f() {
//
f = myObject.Something().then(...);
}

Search for avaliable library before #pragma comment in c++?

I have a piece of code which relies on the "Xinput.lib" file provided by windows in order to interface with a xbox controller.
Recently I installed VS2012 which seems to have caused "Xinput.lib" to no longer be available to the compiler. I found a workaround where I instead I use "Xinput9_1_0.lib" on the system running the VS2012 compiler. This however causes a problem since I am developing on multiple systems where one is running VS2012 and the other is running VS2010. To compile I have to change between "Xinput9_1_0.lib" and "Xinput.lib" within the code.
What I am wondering is if there is a way to search for the available library before using #pragma comment to link the library?
Something like this (I realize this is in no way valid, just a demonstration of intent):
if("Xinput.lib" exists) {
#pragma comment(lib,"Xinput.lib")
}
else if("Xinput9_1_0.lib" exists) {
#pragma comment(lib,"Xinput9_1_0.lib")
}
Use the macro for the particular version of VS you're interested in:
#ifdef MSC_VER < 1700 //pre 2012
#pragma comment(lib,"Xinput.lib")
#else
#pragma comment(lib,"Xinput9_1_0.lib")
#endif

Is it possible to compile boost::recursive_mutex statically in C++ Builder

boost::recursive_mutex and boost::lock_guard seem to use boost_thread-bcb-mt-1_39.dll in C++ Builder 2010. I see that there is also static version - boost_thread-bcb-mt-1_39.lib.
My code is something like this:
boost::recursive_mutex mylock;
//...
boost::lock_guard<boost::recursive_mutex> lock(mylock);
However, if I set compile option to Release and set Dynamic RTL option to False all I get is Mixing a dll boost library with a static runtime is a really bad idea.... Returning Dynamic RTL to True compiles but then it needs additional DLL's - cc32100mt.dll and boost_thread-bcb-mt-1_39.dll.
Is there a way to compile it statically in a single exe? After all, LIB file is provided, it should be possible. Is it a problem with this version of C++ Builder or Boost?
What I needed was to define in a header file:
#define BOOST_THREAD_USE_LIB
right before:
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/locks.hpp>
After then it compiles without any issues.

Automatically Including OpenCV Libraries of Different Versions

I've been automatically including the opencv library files for my c++ code on Visual Studio 2008 on Windows 7 with the following code:
#ifndef NDEBUG
#pragma comment(lib, "opencv_core231d.lib")
#pragma comment(lib, "opencv_highgui231d.lib")
#pragma comment(lib, "opencv_imgproc231d.lib")
#else
#pragma comment(lib, "opencv_core231.lib")
#pragma comment(lib, "opencv_highgui231.lib")
#pragma comment(lib, "opencv_imgproc231.lib")
#endif
but I run into trouble when the system has a different version of the opencv library installed because the .lib files have the version (in this case, 2.31) in the filename. Is there a good way to automatically or near-automatically detect what version of the opencv library is available then slide in the appropriate version string into the pragma?
There are small changes between different OpenCV versions - not much, but enough to crash your app when you change from 2.0 to 2.2 or from 2.2 to 2.3.1. Also, the beta 2.4 release has enough changes from previous ones.
So best is to test your app with an OpenCV version, and deliver it with those dlls only.
A small example:
Mat a(3,3,CV_8UC3);
a.setTo( Scalar(10) ); // in 2.3.1 will set all channels to 10,
// in 2.2 will only set first channel.
The corresponding 2.2 call would be
a.setTo(Scalar::all(10));
Or
a = 0; // runs fine on 2.3.1. Equivalent to setTo().
// Does not compile on earlier versions
Another example is cv::drawPoly(), which has a different signature on 2.2 and 2.3.1.
Given the fact that those changes are not well documented, the chance to miss one of them by mistake is really high.
I have worked out a solution to having code run on various versions of OPENCV by merging the following articles:
How to make a string out of macros
Concatenating strings in macros
Pragma statements in #defines with support for VS2008 here on MSDN
Bonus: How to have global settings defined in a solution
As noted, this can cause some serious grief if you pop between incompatible versions but for those versions and features supported this may be useful to some. Use this technique to set the opencv version once and have your code automatically link to the desired version by either
define the OPENCV_VERSIONin one place in your source code
Define it in a Property Sheet
Define it in a system environment variable.
My code ended up like so:
#include <iostream>
// #define OPENCV_VERSION $(OPENCV_VERSION)
// #define OPENCV_VERSION 220
#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)
#define LINK_TO_OPENCV(libname) __pragma(comment(lib, "opencv_" #libname STR(OPENCV_VERSION)))
#define LINK_TO_OPENCV_DEBUG(libname) __pragma(comment(lib, "opencv_" #libname STR(OPENCV_VERSION) "d"))
#ifndef NDEBUG
LINK_TO_OPENCV_DEBUG("core")
LINK_TO_OPENCV_DEBUG("highgui")
LINK_TO_OPENCV_DEBUG("imgproc")
#else
LINK_TO_OPENCV("core")
LINK_TO_OPENCV("highgui")
LINK_TO_OPENCV("imgproc")
#endif
int main()
{
std::cout << STR(LINK_TO_OPENCV("core")) << "\n";
return 0;
}
And now to set the OPENCV_VERSION anywhere you like. For example, you can have a single header file included by everyone that has the line:
#define OPENCV_VERSION 220
Or you can goto Project->Properties->C/C++->Preprocessor and set Preprocessor Definitions to OPENCV_VERSION=220. Or you can do the same thing in a shared property sheet for the entire solution.
Or, and this is important, you can use this technique to define a global environment variable in windows itself called OPENCV_VERSION_ENV and set its value to the version code (say, 220). Then you can put set the preprocessor definition to OPENCV_VERSION=$(OPENCV_VERSION_ENV) and you will bring in the environment variable into the link command. You CANNOT do a #define OPEN_VERSION $(OPENCV_VERSION_ENV) but since the property pages will automatically translate $(macros) we can get environment variables there.