How to log with pantheios to a file? - c++

I tried the exemple from pantheios to log to a file but can't manage to make it work.
Messages are correctly displayed in the console but the log file isn't created.
I tried to change severity levels since I saw that thread, but no one works.
Here's the code :
/* Pantheios Header Files */
#include <pantheios/pantheios.hpp> // Pantheios C++ main header
#include <pantheios/inserters/args.hpp> // for pantheios::args
#include <pantheios/inserters/exception.hpp> // for pantheios::exception
#include <pantheios/backends/bec.file.h> // be.file header
/* Standard C/C++ Header Files */
#include <exception> // for std::exception
#include <new> // for std::bad_alloc
#include <string> // for std::string
#include <stdlib.h> // for exit codes
/* ////////////////////////////////////////////////////////////////////// */
/* Define the stock front-end process identity, so that it links when using
* fe.N, fe.simple, etc. */
PANTHEIOS_EXTERN_C const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PANTHEIOS_LITERAL_STRING("example.cpp.file");
/* ////////////////////////////////////////////////////////////////////// */
#define PSTR(x) PANTHEIOS_LITERAL_STRING(x)
/* ////////////////////////////////////////////////////////////////////// */
int main(int argc, char **argv)
{
try
{
#ifndef PANTHEIOS_USE_WIDE_STRINGS
pantheios::log_DEBUG("main(", pantheios::args(argc, argv), ")");
#else /* ? !PANTHEIOS_USE_WIDE_STRINGS */
STLSOFT_SUPPRESS_UNUSED(argc); STLSOFT_SUPPRESS_UNUSED(argv);
#endif /* !PANTHEIOS_USE_WIDE_STRINGS */
pantheios::log_NOTICE(PSTR("stmt 1"));
// Set the file name for the local back-end, truncating the
// file's existing contents, if any.
pantheios_be_file_setFilePath(PSTR("log.local"), PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BEID_LOCAL);
pantheios::log_NOTICE(PSTR("stmt 2"));
// Set the file name for the remote back-end.
pantheios_be_file_setFilePath(PSTR("log.remote"), PANTHEIOS_BEID_REMOTE);
pantheios::log_NOTICE(PSTR("stmt 3"));
// Set the file name for all back-ends.
pantheios_be_file_setFilePath(PSTR("log.all"));
pantheios::log_NOTICE(PSTR("stmt 4"));
pantheios::log_DEBUG(PSTR("exiting main()"));
system("pause");
return EXIT_SUCCESS;
}
catch(std::bad_alloc&)
{
pantheios::log(pantheios::alert, PSTR("out of memory"));
}
catch(std::exception& x)
{
pantheios::log_CRITICAL(PSTR("Exception: "), pantheios::exception(x));
}
catch(...)
{
pantheios::logputs(pantheios::emergency, PSTR("Unexpected unknown error"));
}
return EXIT_FAILURE;
}
/* ///////////////////////////// end of file //////////////////////////// */
I have an "include_pantheios.cpp" file for implicit link purpose. Here it is :
/* Pantheios Header Files */
#include <pantheios/implicit_link/core.h>
#include <pantheios/implicit_link/fe.simple.h>
#include <platformstl/platformstl.h>
#include <pantheios/implicit_link/be.file.h>
#if ( defined(UNIX) || \
defined(unix))&& \
( defined(_WIN32) || \
defined(_WIN64))
# include <unixem/implicit_link.h>
#endif /* _WIN32 || _WIN64 */
Does somebody see where my problem come from?
Thanks in advance,
Vincent

I think part of your confusion comes from the example doing too much: it shows local and remote files all in one. A simpler example would be:
// 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>
int main() {
pantheios::log_NOTICE("log-1"); // save until log file set
pantheios_be_file_setFilePath("mylogfile"); // 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"); // sets log file; write "log-3" stmt
pantheios::log_NOTICE("log-4"); // write "log-4" stmt
} // closes "mylogfile2" during program closedown
The problem with the original code, which I think comes from a Pantheios example program, is that it's trying to illustraet how to use local and remote back-ends at the same time as trying to illusteate how to use the be.file backend.
Forget all the different back-ends, and concentrate on the be.file-specific stuff.
HTH

I got the same problem, for future people, the problem is the order to link libraries
Pantheios Forum :
https://sourceforge.net/projects/pantheios/forums/forum/475314/topic/5313841/index/page/1
I just link the pantheios.1.be.file.gcc44 before the pantheios.1.be.fprintf.gcc44

I think the issue is the order in which you link, but I don't quite see how it's possible given the code you posted.
I encountered the same issue, and I realized that it was because I was linking two backends at once: file and fprintf. More specifically, it was because I was linking fprintf before file. When I switched the order to link file first, then it would create and use the log file, but would not output to stdout when I commented out pantheios_be_file_setFilePath. So apparently whichever is linked first is the only one that will work (look up multiple backends).

As far as I can tell this code is identical to the file stock back-end sample given with the library, so it ought to work.
How are you determining that the log files are not written? These are relative paths - try using absolute paths to be sure you are looking in the correct place.
If all else fails, you could debug through the code (after the filepath is set) to find out why nothing is getting written out.

Related

How to make CPP files visible to linker in ESP8266 Eclipse project

There is a "hello world" project in Eclipse IDE that is supposed to compile against ESP8266 RTOS SDK.
File structure is as follows
I added one C++ class to it and put it into its own folder. Here is the class header
#ifndef MAIN_BLINKER_BLINKER_H_
#define MAIN_BLINKER_BLINKER_H_
class Blinker {
public:
Blinker( int period );
int Period() const;
private:
int period_;
};
#endif /* MAIN_BLINKER_BLINKER_H_ */
and the definitions
#include "Blinker.h"
Blinker::Blinker( int period ) :
period_( period )
{}
int Blinker::Period() const {
return this->period_;
}
Main.cpp file is like this
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "blinker/Blinker.h"
extern "C" {
void app_main()
{
auto blnk = Blinker( 3000 );
int i = 0;
while ( 1 ) {
printf( "[%d] Hello beautiful world!\n", i );
i++;
vTaskDelay( blnk.Period() / portTICK_PERIOD_MS );
}
}
}
It compiles but fails at final stage because the linker (or what is supposed to be a linker in xtensa toolchain) does not see definitions of Blinker methods. This is what I get in the build log
If I put class files next to main.cpp file, the build succeeds. However with time there will be hundreds of files, and without any grouping it will quickly turn into an unmanageable mess.
Alternatively I could put this class into top-level components folder and equip it with empty component.mk file. This would also make the build system happy, however it would force me to use ugly header includes like ../components/blinker/Blinker.h, which I would like to avoid.
So the question is how to make build system aware of .c and .cpp files residing in subfolders of main folder?
you can set COMPONENT_SRCDIRS in "main" component.mk file
see:
https://docs.espressif.com/projects/esp8266-rtos-sdk/en/latest/api-guides/build-system.html#example-component-makefiles
Try to add blinker/Blinker.cpp to your CMakeLists.txt.
Take a look at
How to add new source file in CMakeLists.txt?

Entry point could not be located in the dynamic link library - c++

I created a DLL project in visual c++, and I wanted to use the cpprestsdk/casablanca.
Then I created a RestWrapper.h header file:
#pragma once
namespace mycpprest
{
class RestWrapper
{
public:
static __declspec(dllexport) void TestApi();
};
}
And RestWrapper.cpp source file:
#include "stdafx.h"
#include "RestWrapper.h"
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/json.h>
using namespace utility;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace concurrency::streams;
namespace mycpprest
{
void RestWrapper::TestApi()
{
auto fileStream = std::make_shared<ostream>();
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
http_client client(U("http://13.231.231.252:3000/api/individual_employment_setting/detail/172"));
// Build request URI and start the request.
//uri_builder builder(U("/search"));
//builder.append_query(U("q"), U("cpprestsdk github"));
return client.request(methods::GET);
})
// Handle response headers arriving.
.then([=](http_response response)
{
printf("Received response status code:%u\n", response.status_code());
// Write response body into the file.
// return response.body().read_to_end(fileStream->streambuf());
stringstreambuf buffer;
response.body().read_to_end(buffer).get();
//show content in console
printf("Response body: \n %s", buffer.collection().c_str());
//parse content into a JSON object:
//json::value jsonvalue = json::value::parse(buffer.collection());
return fileStream->print(buffer.collection()); //write to file anyway
})
// Close the file stream.
.then([=](size_t)
{
return fileStream->close();
});
// Wait for all the outstanding I/O to complete and handle any exceptions
try
{
requestTask.wait();
}
catch (const std::exception &e)
{
printf("Error exception:%s\n", e.what());
}
}
}
When I build it, It success built.
Then I created Windows Console Application in visual c++ to test the DLL project that I created.
I copy the MyCpprestDll.dll, MyCpprestDll.lib and RestWrapper.h from MycppestDll project into DllTest project.
Then in DllTest project properties, in the Linker->input->Additional Dependencies: I added MyCpprestDll.lib
And here the code of DllTest.cpp:
#include "stdafx.h"
#include "RestWrapper.h"
#include <iostream>
using namespace mycpprest;
int main()
{
RestWrapper::TestApi();
system("PAUSE");
return 0;
}
It has no compile error, but when running the error says:
The procedure entry point ?TestApi#RestWrapper#mycpprest##SAXXZ could not be located in the dynamic link library
I tried to search about the related issues but I don't know how to or what to set to my entry point in my dll project.
You need to use dllexport when building your DLL, but dllimport when you are including it into another project
This answer shows you have to use some macros and pre-processor definitions to make it work.
In your RestWrapper.h header file do something as shown below.
Note that you must use __declspec(dllimport) for the importing executable to access the DLL's public data symbols and objects.
Also, make sure you define the macro RestWrapper_EXPORTS in C/C++->Preprocessor->Preprocessor Definitions in your DLL project properties.
#ifdef RestWrapper_EXPORTS
#define RestWrapper_APIS __declspec(dllexport)
#else
#define RestWrapper_APIS __declspec(dllimport)
#endif
namespace mycpprest
{
// This class is exported from the RestWrapper.dll
class RestWrapper
{
public:
static RestWrapper_APIS void TestApi();
};
}
Rebuild your DLL project. No changes needed in your DllTest project, just compile your DllTest project using the updated RestWrapper.h and RestWrapper.lib file.

Moving function to different file

I had a function to get points inside a 3D arc working inside a file but, trying to order the code into the appropriate folders, I broke it, and I don't know why because I think I am including it correctly.
Originally a lot of calculations were inside a file "messages.cpp", but it is supposed to have just the messages and the calculations should be in Calculations folder.
So now messages.cpp is something like this:
#include "../../FGProcessorModule/Calculations/ArcToPoints.h"
namespace myNamespace {
void MsgProvider::onEvent{
std::vector<Formulas::LLPoint> allPoints = ArcToPoints(center, start, end);
}
}
In "../../FGProcessorModule/Calculations/ArcToPoints.h" I have:
#ifndef ARCTOPOINTS_H
#define ARCTOPOINTS_H
#include blablabla
namespace myNamespace{
std::vector<Formulas::LLPoint> ArcToPoints (Formulas::LLPoint, Formulas::LLPoint, Formulas::LLPoint);
}
#endif /* ARCTOPOINTS_H */
And finally in "../../FGProcessorModule/Calculations/ArcToPoints.cpp" I have:
#include "ArcToPoints.h"
namespace myNamespace{
std::vector<Formulas::LLPoint> ArcToPoints (Formulas::LLPoint center, Formulas::LLPoint start, Formulas::LLPoint end){
//Lots of calculations
}
}
I think everything is OK but I receive this error when I want to compile:
undefined reference to `FVIS::ArcToPoints(Formulas::LLPoint,
Formulas::LLPoint, Formulas::LLPoint)'
I don't know if this will help others as it is a very specific problem, this is a project using ros and catkin.
I was missing including the new created file in CMakeLists.txt. Now it compiled just fine.

Kernel module periodically calling user space program

I want to call a user space program from a kernel module periodically.But the kernel program is freezing the system, while I try to load it.
following is the program,
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/jiffies.h>
#include <linux/time.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/hrtimer.h>
#include <linux/sched.h>
#include <linux/delay.h>
#define TIME_PERIOD 50000
static struct hrtimer hr_timer;
static ktime_t ktime_period_ns;
static enum hrtimer_restart timer_callback(struct hrtimer *timer){
char userprog[] = "test.sh";
char *argv[] = {userprog, "2", NULL };
char *envp[] = {"HOME=/", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
printk("\n Timer is running");
hrtimer_forward_now(&hr_timer, ktime_period_ns);
printk("callmodule: %s\n", userprog);
call_usermodehelper(userprog, argv, envp, UMH_WAIT_PROC);
return HRTIMER_RESTART;
}
static int __init timer_init() {
ktime_period_ns= ktime_set( 0, TIME_PERIOD);
hrtimer_init ( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
hr_timer.function = timer_callback;
hrtimer_start( &hr_timer, ktime_period_ns, HRTIMER_MODE_REL );
return 0;
}
static int __exit timer_exit(){
int cancelled = hrtimer_cancel(&hr_timer);
if (cancelled)
printk(KERN_ERR "Timer is still running\n");
else
printk(KERN_ERR "Timer is cancelled\n");
}
module_init(timer_init);
module_exit(timer_exit);
MODULE_LICENSE("GPL");
test.sh is a script which just echoes a comment.
I have tested the call_usermodehelper part and timer part individually and it is working fine. But while I am combining the two codes, the system hangs.
Can anybody please help me to solve the problem.
Quick look around strongly suggests that hrtimer callbacks are executed from an irq context, which is expected - how else are you going to get high resoluton?
But this also means you must no block, while your callback can block due to call_usermodehelper regardless of NOWAIT passed.
So it seems you are testing your module on a kernel with debugging disabled, which is fundamentally wrong.
But this is less relevant as the thing you are trying to achieve in the first place looks fundamentally wrong.
I can only recommend you elaborate what is the actual problem. There is absolutely now way that forking + execing has anything to do with something requiring a high resolution timer.

C++ Process terminated with status 3 confusion

I am very new to programming, but have been following c++ tutorials and amassing a number of PDFs for the last week or so to help me out. I couldn't find anything in them or online that answered my question clearly enough. Please forgive me for my newbie-ness.
Pertinent code:
Logfile.hpp
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// HEADER :: CLASS INTERFACE FILE
// ==============================
// Include Guard
#ifndef __LOGFILE_INCLUDED__ // If Actor.hpp hasn't been included yet
#define __LOGFILE_INCLUDED__ // Define this for the compiler so it knows it has now been included
// ==============================
// Forward declared dependencies
// ==============================
// Included dependencies
#include <iostream>
#include <fstream>
// ==============================
// Actual class
class Logfile { // Logfile
public:
// Globally accessible variables
bool LACT; // Is log file active?
std::ofstream LOG; // Actual log file
std::string entry; // Data to be entered in log file
// ==============================
// Core methods
Logfile(); // Constructor
~Logfile(); // Destructor
// Additional methods
bool isActive(); // Is log file active?
void logEntry(std::string entry); // Make an entry in the log if 'LACT' is set to true
void toggleLog(); // Toggle log file open or closed
};
extern Logfile *log; // This variable is declared in main
#endif // __LOGFILE_INCLUDED__
Logfile.cpp
// ==============================
// Included dependencies
#include "Logfile.hpp"
// ==============================
// Core methods
Logfile::Logfile() { // Constructor
LACT = true; // Toggle logfile to active
LOG.open ("LOG.txt"); // Open 'log.txt' and prepare it to receive 'LOG' entries
LOG << "LOG FILE CLASS CONSTRUCTED\n";
LOG << "LOG FILE OPENED\n";
}
Logfile::~Logfile() { // Deconstructor
LOG << "LOG FILE CLOSED\n";
LOG << "LOG FILE CLASS DECONSTRUCTED";
LOG.close(); // Close log file
}
// Additional methods
bool Logfile::isActive() { // Is log file active?
if ( LACT ) return true;
else return false;
}
void Logfile::logEntry(std::string entry) { // Make an entry in the log if 'LACT' is set to true
if ( LACT ) LOG << entry << std::endl;
}
void Logfile::toggleLog() { // Toggle log file open or closed
if ( LACT ) { // Log file is active
LOG << "LOG FILE CLOSED\n";
LOG.close(); // Close log file
} else { // Log file is inactive
LOG.open ("LOG.txt"); // Open 'log.txt' and prepare it to receive 'LOG' entries
LOG << "LOG FILE OPENED\n";
}
}
Engine.hpp
// ==============================
// Forward declared dependencies
class Logfile;
class Engine { // Core system, main loop
public :
// Globally accessible variables
Logfile *log; // Declare 'log' as an empty pointer (*)
Engine.cpp
// ==============================
// Included dependencies
#include "Logfile.hpp"
// ==============================
// Core methods
Engine::Engine() { // Constructor method
// Initialization
log = new Logfile(); // Declare 'log' as pointer to access log file
TCODConsole::initRoot(80,50,"Testbed",false); // Create 'root' console (not fullscreen)
if ( log->isActive() ) log->logEntry("(TCODConsole) Root console initialized"); // WORKS
Map.hpp
// ==============================
// Forward declared dependencies
class Logfile;
extern Logfile *log; // Pointer exists in Engine.hpp
Map.cpp
// ==============================
// Included dependencies
#include "Logfile.hpp"
if ( log->isActive() ) log->logEntry("(TCODConsole) Root console initialized"); TERMINATION STATUS 3
if ( tiles[(x-1)+y*width].tType =="floor" ) tally++; // Left tile status, add 1 to tally if floor : TERMINATION STATUS 3
if ( tiles[(x-1)+(y-1)*width].canWalk ) tally++; // Left-top tile status, add 1 to tally if floor : WORKS
If I understand correctly, a termination status 3 indicates that I am referencing a variable incorrectly in regards to whether it's a pointer or not...? I initially ran into the problem when I wanted to access the tType string from an individual tile in the 2Darray in Map.cpp (though I can access the boolean variable canWalk just fine...), and couldn't figure out what was wrong, so I decided to learn to implement an external log to find the problem...but I guess I found my way back to the same issue while doing that...
Any help is greatly appreciated, as is criticism, I have a lot to learn.
--
My initial purpose for asking this question was (now I realize) to get a globally declared object accessible from any *.cpp file in a multi-file program. I just found this answer: http://www.cplusplus.com/forum/beginner/3848/, in case this might be helpful to anyone else with a similar problem.
In your Logfile.hpp you're missing #include <string>: one of your LogFile classes variables are declared std::string so you need to include that.
In your Engine.cpp you forget to include your Engine.hpp where your LogFile *log; variable is declared. this results in an error in your Engine.cpp file where you try assigning a new LogFile object to it.
So add #include <string> to the top of your Logfile.hpp and add #include "Engine.hpp" to the top of your Engine.cpp