I was trying to find a simple way to redirect std::cout outputs to the Visual Studio console window, so that the same code can be used to log on Mac and Windows.
After an hour of searching, I finally found a simple way that works (mostly based on https://stackoverflow.com/a/51498216/3311183)
At the start of my program, I put:
#ifdef _WIN32
#include <ostream>
#include <Windows.h>
#include <string>
#include <sstream>
#endif
And then at the start of any function that I want to redirect std::cout in (i.e. at the top of my main function), I put:
#ifdef _WIN32
std::streambuf* backup;
backup = std::cout.rdbuf();
std::stringstream ss;
std::cout.rdbuf(ss.rdbuf());
#endif
Then, at the bottom of that function (i.e. at the end of my program), I put:
#ifdef _WIN32
OutputDebugString(ss.str().c_str());
std::cout.rdbuf(backup);
#endif
That's it!
Related
I have a small snipped of code, which just produces a function to get the current directory for either Windows or Linux platform:
#include <stdio.h> /* defines FILENAME_MAX */
#include <string>
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
std::string getcwd(){
char mCurrentPath[FILENAME_MAX];
GetCurrentDir(mCurrentPath, sizeof(mCurrentPath));
return *(new std::string (mCurrentPath));
}
This is all great and working; however, I'd like to make the getcwd() function inside the namespace, fUtils, hence I did this:
#include <stdio.h> /* defines FILENAME_MAX */
#include <string>
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
namespace fUtils{
std::string getcwd(){
char mCurrentPath[FILENAME_MAX];
GetCurrentDir(mCurrentPath, sizeof(mCurrentPath));
return *(new std::string (mCurrentPath));
}
}
But this gives an error in VSCode which says:
no matching function for call to 'getcwd'
What mistake am I making in this? If this isn't how I put the function to the namespace fUtils, then how should I put it into the namespace?
Your fUtils::getcwd() function is attempting to call itself when the GetCurrentDir macro is evaluated (to getcwd), and this results in a function that expects no argument but is being given two arguments.
To resolve this, add the global namespace operator (::) in the definitions for GetCurrentDir, as follows:
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir ::_getcwd
#else
#include <unistd.h>
#define GetCurrentDir ::getcwd
#endif
Then, in your function body, it is clear to the compiler that your aren't looking for a 'recursive' (and invalid) call.
Use of macros in such context is invitation to problems in future.
Just wrap those functions with own API and all problems will be resolved.
Header file:
#include <string>
namepsace fUtils {
std::string getcwd();
}
Then you can have platform specific cpp files, Windows:
namepsace fUtils {
std::string getcwd() {
char mCurrentPath[FILENAME_MAX];
::_getcwd(mCurrentPath, sizeof(mCurrentPath));
return {mCurrentPath};
}
}
Mac version is obvious.
You also can use this macros inside single cpp file and this way contain them there if you do not what to do larger clean up.
Side notes:
there is boost::filesystem which has such api also use of boost::filesystem::path is quite handy
C++17 introduces std::filesystem, but it is not well supported yet (for example MacOS)
if you wrap this functionality in classes you will open your way for better testing (mocks).
Hi I'm been struggling to get my preprocessor to quit bugging me about this:
So I added _CRT_SECURE_NO_WARNINGS in the C/C++ -> preprocessor -> definitions
But it still said the same, so I defined it below as shown in the code below.
though it didnt work. It is shown in output as an error though and not a warning. Is there anything else I should do?
#include "texture.h"
#include <iostream>
#define _CRT_SECURE_NO_WARNINGS
#include "stb_image.h"
#define STB_IMAGE_IMPLEMENTATION
Texture::Texture(const std::string& fileName)
{
int width, height, numComponents;
unsigned char* data = stbi_load((fileName).c_str(), &width, &height,
&numComponents, 4);
//rest isnt really neccesary i guess
You need to put #define _CRT_SECURE_NO_WARNINGS at the very beginning of the program:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
int main()
{
FILE *f = fopen("a", "r");
}
But following compiles with the warning because #define _CRT_SECURE_NO_WARNINGS comes after #include <iostream>:
#include <iostream>
#define _CRT_SECURE_NO_WARNINGS
int main()
{
FILE *f = fopen("a", "r");
}
The same for #pragma warning(disable: 4996), you need to put it at the beginning of the program (or at least before #include <iostream>)
Consider using
#pragma warning(disable: 4996)
instead.
Do not define _CRT_SECURE_NO_WARNINGS or other warning suppressions, it is a workaround that is supposed to be used when upgrading code not yet utilizing security enhancements in CRT. Fix the code that is causing them.
I am seeing the message
/usr/include/wchar.h:89:10: fatal error: 'stdarg.h' file not found
on the console when I save .cpp files in Sublime Text 3, Apple LLVM version 8.0.0 (clang-800.0.38), macOS Sierra. The files do seem to save and build correctly, however. I would appreciate it if anyone could help me understand what is going on.
Edit: I am just starting out with C++, but the line in question appears to come from the default "wchar.h" file on macOS, the relevant lines of which are
#ifndef _WCHAR_H_
#define _WCHAR_H_
#include <_types.h>
#include <sys/cdefs.h>
#include <Availability.h>
#include <sys/_types/_null.h>
#include <sys/_types/_size_t.h>
#include <sys/_types/_mbstate_t.h>
#include <sys/_types/_ct_rune_t.h>
#include <sys/_types/_rune_t.h>
#include <sys/_types/_wchar_t.h>
#ifndef WCHAR_MIN
#define WCHAR_MIN __DARWIN_WCHAR_MIN
#endif
#ifndef WCHAR_MAX
#define WCHAR_MAX __DARWIN_WCHAR_MAX
#endif
#include <stdarg.h>
The error message shows up when I save a file like this:
#include "std_lib_facilities.h"
int main()
{
cout << "Hello, World!\n";
return 0;
}
where "std_lib_facilities.h" is from http://stroustrup.com/Programming/PPP2code/std_lib_facilities.h, but the error message does not appear to be specific only to this file.
I am programming a little engine and I want to implement a debug mode. I tried to write to the console when I am linking the file with #include but it doesn't work. Here what I am trying to do :
main.cpp
#ifdef _DEBUG
#include "debug.h"
#include "vld.h"
#endif
int main(int argc, char** argv){
// some code
return 0;
}
Debug.h
#ifndef __DEBUG_H
#define __DEBUG_H
#include <iostream>
#ifdef _DEBUG
std::cout << "DEBUG MODE" << std::endl;
#endif
#endif
I kept only the code that was essential. I do understand that I need to execute the std::cout inside the main but I can't because I want the DEBUG MODE to be printed first in the console. The #include vld.h is an external header file that does what I am trying to do ( I don't have access to that file ).
I am trying to implement a test project using the Point Cloud Library and OpenCV with multiple files. When I try to compile, I get the "already defined error" message. Probably I'm doing something stupid that cannot realize for some reason - I tried out a couple of solutions found here, none of them seemed to be help in my case.
What I have:
A libs.h file, where I load the lib files (in Project properties, I only set up the .lib paths and load the libs "by hand", like the headers):
#pragma once
#ifndef PCLTEST_LIBS
#define PCLTEST_LIBS
#ifdef _DEBUG
#pragma comment(lib, "pcl_apps-gd.lib")
#pragma comment(lib, "pcl_common-gd.lib")
// a bunch of other debug libs
#else
// the release libs
#endif
#endif
A main file from which I basically deleted everything at this point to debug:
// load the libs
#ifndef PCLTEST_LIBS
#include "libs.h"
#endif
// pcltest includes
// if only this first one is #included, everything is OK
#include "opencvOperations.h"
// #including this one causes the error
#include "files.h"
// these ones are not working also
//#include "cloudOperations.h"
//#include "visualize.h"
// c++ headers
#include <stdio.h>
#include <string>
//#include <sstream>
//#include <iostream>
void writeInfo()
{
// some std::cout calls
}
int main( int argc, char* argv[] )
{
writeInfo();
// this function is in opencvOperations.h and works OK
pcltest::openLena();
}
Then I get several error messages in my main.obj that some (PCL related) symbols are already defined in files.obj. I use PCL related calls both in opencvOperations and files, the first one is OK, the second one does not work.
Edit:
To add more detail, my files.h header:
#pragma once
#ifndef PCLTEST_FILES
#define PCLTEST_FILES
// pcl headers
#ifndef PCL_COMMON_H_
#include <pcl/common/common_headers.h>
#endif
#ifndef PCL_IO_FILE_IO_H_
#include <pcl/io/file_io.h>
#endif
#ifndef PCL_IO_PCD_IO_H_
#include <pcl/io/pcd_io.h>
#endif
#ifndef PCL_IO_PLY_IO_H_
#include <pcl/io/ply_io.h>
#endif
// boost headers
#ifndef BOOST_FILESYSTEM_OPERATIONSX_HPP
#include <boost/filesystem/operations.hpp>
#endif
#endif
namespace pcltest
{
// function to open PCL or binary PLY files
pcl::PointCloud<pcl::PointXYZ>::Ptr openCloud(std::string filename);
// function to save the point cloud to PCD format
void saveCloud();
}
Before splitting the code into separate files, everything worked well (with the same project settings).
Edit2:
I located the source of the problem,
#include <pcl/io/ply_io.h>
causes this. For now, I got rid of everything related to PLY and everything works fine. I'll look at it later, this might be a PCL library specific issue. Still strange to me why this call causes linker error in an other file, where I don't even use PLY related functions/variables.
I had the same problem as you had. I had a surface.h and surface.cpp file, and I found out that I had to include the ply_io.h file from surface.cpp rather than surface.h and now it compiles fine. I hope that helps or makes sense! haha
If a constant is being instantiated in an include one can also use selectany, per http://msdn.microsoft.com/en-us/library/5tkz6s71%28v=vs.80%29.aspx -- in my case:
const int CSdata[] = {1, 2, 3, 4};
when included in more than one source part produces LNK2005 at link time, avoided via:
const __declspec(selectany) int CSdata[] = {1, 2, 3, 4};
Non-portable, yeah ...