How to play with spdlog? - c++

I downloaded and followed the example 1.
Moved to example 2 (Create stdout/stderr logger object) and got stuck. Actually I can run it as it is but if I change
spdlog::get("console") to spdlog::get("err_logger") it crashes.
Am I supposed to change it like that?
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
void stdout_example()
{
// create color multi threaded logger
auto console = spdlog::stdout_color_mt("console");
auto err_logger = spdlog::stderr_color_mt("stderr");
spdlog::get("err_logger")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");
}
int main()
{
stdout_example();
return 0;
}
I also tried Basic file logger example:
#include <iostream>
#include "spdlog/sinks/basic_file_sink.h"
void basic_logfile_example()
{
try
{
auto logger = spdlog::basic_logger_mt("basic_logger", "logs/basic-log.txt");
}
catch (const spdlog::spdlog_ex &ex)
{
std::cout << "Log init failed: " << ex.what() << std::endl;
}
}
int main()
{
basic_logfile_example();
return 0;
}
And I see it creates basic-log.txt file but there is nothing on it.

Because you need to register err_logger logger first. There is no default err_logger as far as I know. spdlog::get() returns logger based on its registered name, not variable.
You need a code like this. Code is complex and you may not need all of it though:
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/rotating_file_sink.h"
void multi_sink_example2()
{
spdlog::init_thread_pool(8192, 1);
auto stdout_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt >();
auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("mylog.txt", 1024*1024*10, 3);
std::vector<spdlog::sink_ptr> sinks {stdout_sink, rotating_sink};
auto logger = std::make_shared<spdlog::async_logger>("err_logger", sinks.begin(), sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block);
spdlog::register_logger(logger); //<-- this line registers logger for spdlog::get
}
and after this code, you can use spdlog::get("err_logger").
You can read about creating and registering loggers here.
I think spdlog::stderr_color_mt("stderr"); registers logger with name stderr so spdlog::get("stderr") may work, but have not tested myself.

Related

I invoke LSCopyApplicationURLsForURL() using C++, but get a segment fault

I want to write a C++ program to get associated applications which are suitable to open specified file. I find the LSCopyApplicationURLsForURL API, and create a command line C++ application by XCode.
But after running this program, I always get segment fault. XCode shows EXEC_BAD_ACCESS(code=1, address....) error.
I also tryied running it from sudo, but the same result. What is the problem?
The code:
#include <iostream>
#include <objc/objc.h>
#include <objc/objc-runtime.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
using namespace std;
int main(int argc, const char * argv[]) {
auto url = CFURLRef("file:///Users/efan/src/a.cpp");
auto ret = LSCopyApplicationURLsForURL(url, kLSRolesAll);
cout << ret << endl;
return 0;
}
Try creating your CFURLRef using one of the proper CFURLCreate* methods. See "Creating a CFURL" here.
For example:
auto tempStringURL = CFStringCreateWithCString(nullptr, "/Users/efan/src/a.cpp", kCFStringEncodingUTF8);
auto url = CFURLCreateWithFileSystemPath(nullptr, tempStringURL, kCFURLPOSIXPathStyle, FALSE);
auto ret = LSCopyApplicationURLsForURL(url, kLSRolesAll);
You need to Release the "Created" variables to clean up memory.

Executing more than one FrontendAction on a CompilerInstance in clang

I have a single cpp file of about 100 lines with the following contents.
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendActions.h>
#include <iostream>
// The filename that will be processed (twice).
static const char* FILENAME = "simple.cpp";
// System header locations, you may need to
// adjust these.
static const char* SYSTEM_HEADERS[] =
{
"/usr/include/c++/5.4.0",
"/usr/include/x86_64-linux-gnu/c++/5.4.0",
"/usr/include/c++/5.4.0/backward",
"/usr/local/lib/clang/4.0.0/include",
"/usr/include/x86_64-linux-gnu",
"/usr/include"
};
// Location for builtin headers. You may need to
// adjust this.
static const char* RESOURCE_DIR = "/usr/local/lib/clang/4.0.0";
// Uncomment this to see header search paths.
// #define PRINT_HEADER_SEARCH_PATHS
// Constructs a CompilerInvocation
// that must be fed to a CompilerInstance.
clang::CompilerInvocation* makeInvocation();
// Executes a single SyntaxOnlyAction on
// the given CompilerInstance.
void secondCallThisFunctionFails(clang::CompilerInstance& instance);
int main()
{
using namespace clang;
CompilerInstance instance;
instance.createDiagnostics();
instance.setInvocation(makeInvocation());
instance.getFrontendOpts().Inputs.emplace_back
(
FILENAME,
FrontendOptions::getInputKindForExtension(FILENAME)
);
// First call is OK.
secondCallThisFunctionFails(instance);
// Second call results in assertion failures.
secondCallThisFunctionFails(instance);
return 0;
}
clang::CompilerInvocation* makeInvocation()
{
using namespace clang;
auto invocation = new CompilerInvocation();
invocation->TargetOpts->Triple = llvm::sys::getDefaultTargetTriple();
invocation->setLangDefaults(
*invocation->getLangOpts(),
IK_CXX,
llvm::Triple(invocation->TargetOpts->Triple),
invocation->getPreprocessorOpts(),
LangStandard::lang_cxx11);
auto& headerSearchOpts = invocation->getHeaderSearchOpts();
#ifdef PRINT_HEADER_SEARCH_PATHS
headerSearchOpts.Verbose = true;
#else
headerSearchOpts.Verbose = false;
#endif
headerSearchOpts.UseBuiltinIncludes = true;
headerSearchOpts.UseStandardSystemIncludes = true;
headerSearchOpts.UseStandardCXXIncludes = true;
headerSearchOpts.ResourceDir = RESOURCE_DIR;
for (const auto sytemHeader : SYSTEM_HEADERS)
{
headerSearchOpts.AddPath(sytemHeader, frontend::System, false, false);
}
return invocation;
}
void secondCallThisFunctionFails(clang::CompilerInstance& instance)
{
using namespace clang;
SyntaxOnlyAction action;
if (instance.ExecuteAction(action))
{
std::cout << "Action succeeded.\n";
}
else
{
std::cout << "Action failed.\n";
}
}
As you can see, the main function is quite simple, and calls a function twice at the end. The second time this function is called I get an assertion failure, which surprises me.
The contents of the file simple.cpp is
// test wether we actually configured C++11 or greater
#include <thread>
int main() { return 0; }
The output of this program on my machine is:
Action succeeded.
clangapitest: ../tools/clang/lib/Basic/SourceManager.cpp:819: clang::FileID clang::SourceManager::getFileIDLoaded(unsigned int) const: Assertion `0 && "Invalid SLocOffset or bad function choice"' failed.
Aborted (core dumped)
The problem is: I want to execute more than one action on a CompilerInstance. What state do I have to reset in order to not get assertion failures?
To build it yourself you have to link with some static clang and llvm libraries. Here's the CMakeLists.txt file if interested:
add_clang_executable(clangapitest clangapitest.cpp)
target_link_libraries(clangapitest clangFrontend)
I made a new directory path/to/llvm/tools/clang/tools/clangapitest and adjusted the CMakeLists.txt file in path/to/llvm/tools/clang/tools/CMakeLists.txt to have an extra line add_subdirectory(clangapitest).
Well, I figured it out. In the doxygen documentation of CompilerInstance::ExecuteAction, it states that an invocation object and diagnostics object should have been initialized, and no other state (hence no source nor filemanager). So the following works:
SyntaxOnlyAction action;
instance.setSourceManager(nullptr);
instance.createDiagnostics();
if (instance.ExecuteAction(action))
{
std::cout << "Action succeeded.\n";
}
else
{
std::cout << "Action failed.\n";
}

std::cout not showing on screen

This is a fairly simple problem I can't get my head around. It was working before and suddenly now that I'm using std::cout, in the Visual Studio 2013 output window I do not see the output, but I see a bunch of background executions happening. I feel I have messed up something. This is App Game Kit project using C++.
Here's the simple code to output:
#include "template.h"
#include <iostream>
using namespace AGK;
app App;
void app::Begin(void)
{
agk::SetVirtualResolution (1024, 768);
agk::SetClearColor( 151,170,204 );
agk::SetSyncRate(60,0);
agk::SetScissor(0,0,0,0);
std::cout << "Hello"; // SIMPLE PRINT
}
void app::Loop (void)
{
agk::Print( agk::ScreenFPS() );
agk::Sync();
// std::cout << "Hello"; // TRIED HERE TOO (works like update() in Unity3D)
}
This is what my debug window is showing, instead of printing "Hello":
FYI, the program is working perfectly without any errors. Am I looking at the wrong window? where can find my output?
for logging, i write my entries to a file. here is the Contents of my log method in cpp:
void MyFileUtils::log(string msg)
{
ofstream log("logfile.txt", ios_base::app | ios_base::out);
log << msg << endl;
return;
}
i then just call this whenever i want to log something. i have it as a singleton. Then i just look in my media subfolder to see the contents of logfile.txt
Try using this before you return from the method:
log.flush();
log.close();

Pantheios write to extenal file

I looked around and I couldn't find the answer to how exactly to do this. I am trying to use Pantheios for logging and I want to write to an external file (otherwise whats the point). I am following one of the examples provided but It doesn't seem to be making the log file anywhere. Here is the code:
Edit: Also pantheios_be_file_setFilePath is returning -4 (PANTHEIOS_INIT_RC_UNSPECIFIED_FAILURE) so thats.....not helpful
#include "stdafx.h"
#include <pantheios/pantheios.hpp>
#include <pantheios/implicit_link/core.h>
#include <pantheios/implicit_link/fe.simple.h>
#include <pantheios/implicit_link/be.WindowsConsole.h>
#include <pantheios/implicit_link/be.file.h>
#include <pantheios/frontends/fe.simple.h>
#include <pantheios/backends/bec.file.h>
#include <pantheios/inserters/args.hpp>
PANTHEIOS_EXTERN_C const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PANTHEIOS_LITERAL_STRING("LogTest");
int _tmain(int argc, _TCHAR* argv[])
{
try
{
pantheios_be_file_setFilePath(PANTHEIOS_LITERAL_STRING("testlogforme.log"), PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BEID_ALL);
pantheios::log(pantheios::debug, "Entering main(", pantheios::args(argc,argv, pantheios::args::arg0FileOnly), ")");
pantheios::log_DEBUG("debug yo");
pantheios::log_INFORMATIONAL("informational fyi");
pantheios::log_NOTICE("notice me!");
pantheios::log_WARNING("warning!!");
pantheios::log_ERROR("error omg");
pantheios::log_CRITICAL("critical!!!");
pantheios::log_ALERT("alert mang");
pantheios::log_EMERGENCY("EMERGENCY!!!!!");
pantheios_be_file_setFilePath(NULL, PANTHEIOS_BEID_ALL);
system("pause");
return EXIT_SUCCESS;
}
catch(std::bad_alloc&)
{
pantheios::log_ALERT("out of memory");
}
catch(std::exception& x)
{
pantheios::log_CRITICAL("Exception: ", x);
}
catch(...)
{
pantheios::puts(pantheios::emergency, "Unexpected unknown error");
}
return EXIT_FAILURE;
}
Maybe I'm not calling a method or maybe its not being saved to a good location?
It turns out that some of the examples out there for pantheios are incorrect. You DO need to call pantheios_init() even if you are in C++. Here Is the example I got to work after deleting all my code and implementing an example that works.
// Headers for main()
#include <pantheios/pantheios.hpp>
#include <pantheios/backends/bec.file.h>
// Headers for implicit linking
#include <pantheios/implicit_link/core.h>
#include <pantheios/implicit_link/fe.simple.h>
#include <pantheios/implicit_link/be.file.h>
PANTHEIOS_EXTERN_C const char PANTHEIOS_FE_PROCESS_IDENTITY[] = "testLOL";
int main()
{
if(pantheios::pantheios_init() < 0)
{
return 1;
}
pantheios::log_NOTICE("log-1"); // save until log file set
pantheios_be_file_setFilePath("mylogfile.log"); // sets log file; write "log-1" stmt
pantheios::log_NOTICE("log-2"); // write "log-2" stmt
pantheios_be_file_setFilePath(NULL); // close "mylogfile"
pantheios::log_NOTICE("log-3"); // save until log file set
pantheios_be_file_setFilePath("mylogfile2.log"); // sets log file; write "log-3" stmt
pantheios::log_NOTICE("log-4"); // write "log-4" stmt
//system("pause");
return 0;
} // closes "mylogfile2" during program closedown
I found the example on a different post on stack overflow but like I said, the built in examples do not work.

C++ Builder console application that calls a webservice (hello world)

I am trying write a "Hello World" example using C++Builder. This is my first project so I have probably made a simple mistake.
I want to create a console application that calls a calculator web service.
I open C++Builder 2007 and I create a Console Application. A cpp file called File1.cpp appears. Here it is the content:
//---------------------------------------------------------------------------
#include <iostream.h>
#include <vcl.h>
#pragma hdrstop
#include "calculator.h"
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
double a, b;
cout << "Enter the values to sum\n";
cout << "A: ";
cin >> a;
cout << "B: ";
cin >> b;
cout << "\nA+B:";
cout << GetCalculatorSoap()->Add(1,2);
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
Additionally I added the soap proxy going into New->Other->WebService->WSDL Importer.
Using the WSDL http://www.dneonline.com/calculator.asmx?WSDL
This action added calculator.cpp:
// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL : http://www.dneonline.com/calculator.asmx?WSDL
// >Import : http://www.dneonline.com/calculator.asmx?WSDL:0
// Encoding : utf-8
// Version : 1.0
// (21/02/2012 19:48:31 - - $Rev: 10138 $)
// ************************************************************************ //
#include <vcl.h>
#pragma hdrstop
#if !defined(calculatorH)
#include "calculator.h"
#endif
namespace NS_calculator {
_di_CalculatorSoap GetCalculatorSoap(bool useWSDL,
AnsiString addr, THTTPRIO* HTTPRIO)
{
static const char* defWSDL= "http://www.dneonline.com/calculator.asmx?WSDL";
static const char* defURL = "http://www.dneonline.com/calculator.asmx";
static const char* defSvc = "Calculator";
static const char* defPrt = "CalculatorSoap";
if (addr=="")
addr = useWSDL ? defWSDL : defURL;
THTTPRIO* rio = HTTPRIO ? HTTPRIO : new THTTPRIO(0);
if (useWSDL) {
rio->WSDLLocation = addr;
rio->Service = defSvc;
rio->Port = defPrt;
} else {
rio->URL = addr;
}
_di_CalculatorSoap service;
rio->QueryInterface(service);
if (!service && !HTTPRIO)
delete rio;
return service;
}
// ************************************************************************ //
// This routine registers the interfaces and types exposed by the WebService.
// ************************************************************************ //
static void RegTypes()
{
/* CalculatorSoap */
InvRegistry()->RegisterInterface(__interfaceTypeinfo(CalculatorSoap),
L"http://tempuri.org/", L"utf-8");
InvRegistry()->RegisterDefaultSOAPAction(__interfaceTypeinfo(CalculatorSoap),
L"http://tempuri.org/%operationName%");
InvRegistry()->RegisterInvokeOptions(__interfaceTypeinfo(CalculatorSoap),
ioDocument);
}
#pragma startup RegTypes 32
}; // NS_calculator
When I run the application it raises an exception when calling GetCalculatorSoap()->Add(1,2):
---------------------------
Debugger Exception Notification
---------------------------
Project Test.exe raised exception class EOleSysError
with message 'CoInitialize has not been called'.
---------------------------
Break Continue Help
---------------------------
Debugging it seems the GetCalculatorSoap() executes ok, but just before calling the Add method the exception is thrown...
Any ideas what is wrong? Thanks!
The error message tells you what the problem is - CoInitialize has not been called. (Actually, it's preferable to call CoInitializeEx instead, but either will work.)
Your SOAP code is using COM methods, and therefore COM has to be initialized first. This is done on a per-thread basis.
You can fix it by calling CoInitialize(NULL);' at the beginning of your main function. Don't forget to call CoUnitialize(); at the end of main as well.
In Delphi, CoInitialize/CoUninitialize are declared in the ActiveX unit. In C++Builder, it seems to be in OBJBASE.H (a quick search found it there, and that's also what's indicated in the MSDN documentation.
(If you're used to writing VCL form based apps, you won't have seen this before; the VCL initializes COM for you automatically. You're seeing it now because you're writing a console app.)