I have a cpp project, a cpp cli project and a c# win forms project.
I use pantheios log library in my cpp native project. When i try to write log, i take this error :
Here is my codes :
Log.hpp
#ifndef INCLUDE_LOG_HPP
#define INCLUDE_LOG_HPP
#define PANTHEIOS_NO_INCLUDE_OS_AND_3PTYLIB_STRING_ACCESS // Faster compilation
/* Pantheios Header Files */
#include <pantheios/pantheios.hpp> // Pantheios C++ main header
#include <pantheios/inserters/args.hpp> // for pantheios::args
#include <pantheios/backends/bec.file.h> // be.file header
#include "Include/utility.hpp"
/* Standard C/C++ Header Files */
#include <exception> // for std::exception
#include <new> // for std::bad_alloc
#include <string> // for std::string
#include <stdlib.h>
#include <sstream>
#define PSTR(x) PANTHEIOS_LITERAL_STRING(x)
namespace Mtx
{
namespace log
{
class MTXMANAGER Logger
{
public:
void WriteLogIn(const std::string & log_text);
Logger();
~Logger();
};
}
}
#endif
Log.cpp
#include "Log.hpp"
namespace Mtx
{
namespace log
{
PANTHEIOS_EXTERN_C const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PANTHEIOS_LITERAL_STRING("mtx");//
Logger::Logger()
{
char path[MAX_PATH];
GetModuleFileName( NULL, path, MAX_PATH );
std::string::size_type pos = std::string( path ).find_last_of( "\\" );
strcpy(path,std::string( path ).substr( 0, pos).c_str());
std::strcat (path,"\\mtx-%D__.log");
/////
pantheios_be_file_setFilePath(PSTR(path), PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BE_FILE_F_SHARE_ON_WINDOWS, PANTHEIOS_BEID_ALL);
}
Logger::~Logger()
{
}
void Logger::WriteLogIn(const std::string & log_text)
{
pantheios::log_INFORMATIONAL(PSTR(" [1] "),PSTR(log_text));
}
}
}
I take the error at this line :
pantheios::log_INFORMATIONAL(PSTR(" [1] "),PSTR(log_text));
How can i fix this error?
I am afraid I don't have a direct answer for you, but comparing what I have in my solution (which is similar in many aspects with your setup - .NET DLL calling a C++-native DLL, which has Pantheios-logging), here is what I have:
I have a project LOG, which has an InitInstance() and ExitInstance() (and ctors for the CWinApp-derived class - CLogApp)
CLogApp ctor/dtor are empty
The code in InitInstance() and ExitInstance():
BOOL CLogApp::InitInstance()
{
CWinApp::InitInstance();
int panres = pantheios::pantheios_init();
if( panres < 0 )
{
OutputDebugStringA("Could not initialise the Pantheios logging libraries!\n");
util::onBailOut(pantheios::emergency, "Failed to initialise the Pantheios libraries", PANTHEIOS_FE_PROCESS_IDENTITY, /*pantheios::*/pantheios_getInitCodeString(panres));
return FALSE;
}
else
{
pantheios_be_file_setFilePath(CErrorHandler::getLogPath().c_str(), PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BEID_LOCAL);
PANTHEIOS_TRACE_NOTICE("STARTING LOGGING");
}
return TRUE;
}
int CLogApp::ExitInstance()
{
PANTHEIOS_TRACE_NOTICE("STOPPING LOGGING");
pantheios_uninit();
return 0;
}
I am not sure if this will help, but this code has been working for me for many years now.
Related
here is my code which is run on windows:
Log.h
#include <iostream>
#include <sstream>
#include <fstream>
#include <shared_mutex>
#include <thread>
#include <iomanip>
class Log {
public:
static std::ofstream myfile;
static std::shared_mutex m_smutex;
static bool isLogEnabled();
static void close() {
Log::myfile.close();
}
template< typename... Args >
static void debug(const char* format, Args... args) {
std::unique_lock<std::shared_mutex> lock(Log::m_smutex);
if (isLogEnabled()) {
if (!Log::myfile.is_open()) {
Log::myfile.open("C:\\tmp\\log.txt", std::ios_base::app);
}
...
Log::myfile.close();
}
else {
if (Log::myfile.is_open()) {
Log::myfile.flush();
Log::myfile.close();
}
}
}
};
You can see I've deleted most of the code(...) because I narrowed down the problem.
Log.cpp
#include <Windows.h>
#include "Log.h"
std::ofstream LogLine::myfile;
std::shared_mutex LogLine::m_smutex;
bool LogLine::isLogEnabled() {
CHAR regeditPath[MAX_PATH] = { 0 };
CHAR variable[] = "DEBUG_LOGS";
GetEnvironmentVariableA(variable, regeditPath, MAX_PATH);
return GetLastError() == ERROR_ENVVAR_NOT_FOUND ? false : true;
}
The process needs to be run always, that's why I open and close the file everytime I log something. I want to be able to delete logs even when the process is still running. Maybe this is silly because there might be a flag which would allow me to delete the logs while file is open by some process.
Example usage:
Log::debug("little test %d", 10);
As you can see I use mutex because I want to call debug function from different threads. The problem is that after some time I get error code Abort() has been called but I can't understand why.
P.S
I created this code inside custom Credential Provider to enable debugging, but I'm checking in the internet and it seems like nobody is using logging there. Is it because it's forbidden? Maybe this is reason of the crash?
I am new to C++/WinRT and the concurrency/thread topics for c++. I have an odd issue because I've usually create header files for my .cpp files. I ran into an error when trying to prototype my IAsyncAction coroutines in my .h file. I've reproduced the same error in a new test project.
Error: E0311 cannot overload functions distinguished by return type alone
Here's the .h file:
#pragma comment(lib, "windowsapp")
#include <iostream>
#include <ppltasks.h>
#include <pplawait.h>
#include <Windows.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Syndication.h>
IAsyncAction DoWorkOnThreadPoolAsync(int a);
void errTest();
And the .cpp file:
#include "testing.h"
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;
using namespace std::chrono_literals;
concurrency::task<std::wstring> RetrieveFirstTitleAsync()
{
return concurrency::create_task([]
{
for (int i = 0; i < 6; i++)
{
Sleep(1000);
printf("4\n");
}
Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
SyndicationClient syndicationClient;
SyndicationFeed syndicationFeed{ syndicationClient.RetrieveFeedAsync(rssFeedUri).get() };
return std::wstring{ syndicationFeed.Items().GetAt(0).Title().Text() };
});
}
int main()
{
winrt::init_apartment();
printf("0\n");
auto firstTitleOp{ DoWorkOnThreadPoolAsync(1) };
auto countLoop{ RetrieveFirstTitleAsync() };
printf("1 \n");
Sleep(2000);
printf("2 \n");
Sleep(2000);
printf("5 \n");
firstTitleOp.get();
std::wcout << countLoop.get() << std::endl;
printf("3 \n");
}
IAsyncAction DoWorkOnThreadPoolAsync(int a)
{
co_await winrt::resume_background(); // Return control; resume on thread pool.
uint32_t result = 6;
for (uint32_t x = 0; x < 15; ++x)
{
// Do compute-bound work here.
co_await 400ms;
printf("x: %d \n", x);
}
co_return;
}
void errTest() {
}
If I delete the prototype from the .h file and prototype it at the top of the .cpp, it builds. Also if I move the function above any other function that calls it, the project builds (makes sense). I'm just curious if there's a way to prototype it in the header file so I can call it from other .cpp files.
In the h-file you didn't provide the namespace winrt::Windows::Foundation where the IAsyncAction is defined.
You have two options here: (1) move the
using namespace winrt;
using namespace Windows::Foundation;
to the header file or (2) use the full scope:
winrt::Windows::Foundation::IAsyncAction DoWorkOnThreadPoolAsync(int a);
I am trying to access C++ function from C program using Visual Studio 2012 IDE. When I am debugging, I am getting the below error in TestCpp.cpp, in Method: helloworld(), in Line: http_client cli( U("http://localhost:55505/api/Notification"));
Unhandled exception at 0x0000000076D23290 (ntdll.dll) in MyTestCLib.exe: 0xC0000005:
Access violation reading location 0x00000621BC90B128.
Please find the code snippet below.
MyTestCLib.c
#include <ctype.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <my_global.h>
#include <mysql.h>
#include <m_ctype.h>
#include "TestCpp.h"
int main()
{
helloWorld();
return 0;
}
TestCpp.h
#ifndef HEADER_FILE
#define HEADER_FILE
#ifdef __cplusplus
extern "C" {
#endif
void helloWorld();
#ifdef __cplusplus
}
#endif
#endif
TestCpp.cpp
// Calling REST API from C++ using C++ REST API SDK
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <iostream>
#include "TestCpp.h"
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
using namespace std;
void helloWorld()
{
http_client cli( U("http://localhost:55505/api/Notification") );
ostringstream_t uri;
uri << U("/PostNotification");
json::value bodyarray = json::value::array();
json::value body = json::value::object();
body[U("TicketNumber")] = json::value::string( U("25868") );
body[U("NotificationMessage")] = json::value::string( U("Test Notification Message") );
bodyarray[0] = body;
http_response response = cli.request( methods::POST, uri.str(), bodyarray.serialize(), U("application/json") ).get();
if ( response.status_code() == status_codes::OK &&
response.headers().content_type() == U("application/json") )
{
json::value json_response = response.extract_json().get();
ucout << json_response.serialize() << endl;
}
else
{
ucout << response.to_string() << endl;
getchar();
}
}
From MyTestCLib.c You call helloWorld declared as C, but complier creates only C++ function version. This call faill because C++ function uses CPU registry and stack different way. There is simple solution. Create C version of function with different name.
TestCpp.h
#ifdef __cplusplus
void helloWorld();
#else
void c_helloWorld();
#endif
TestCpp.cpp
#include "TestCpp.h"
void helloWorld(void)
{
/* cpp code */
}
extern "C" {
void c_helloWorld(void) // C version of helloWorld
{
helloWorld(); // call cpp helloWorld
}
}
Source file with .c extension is complied by C-Compiler. It can't call C++ function. But in .cpp file complied by C++ Compler you can create C function. This "C" function (c_helloWorld) in compiled by C++ compiler and can be called from C-Complier. It can also call C++ function.
//main.cpp
#include <iostream>
#include "worldActions.h"
using namespace std;
bool worldEvents = false;
void worldReactions(bool world);
int main (int argc, const char * argv[])
{
while (true)
{
if (worldAction == true)
{
worldEvents = true;
worldReactions(worldEvents);
}
else
{
worldEvents = false;
break;
}
}
return 0;
}
//1.cpp
#include <iostream>
#include "worldActions.h"
using namespace std;
bool worldAction;
//header
#ifndef worldActions_h
#define worldActions_h
bool worldAction = true;
#endif /* defined(__asdf_Story__worldActions__) */
When ever extern is used I get linking errors and when it's not I get redefinition errors. How can I fix this so I can use a global boolean?
You use extern bool worldAction; in the header and put the definition in the cpp file.
You are currently compiling a global worldAction into each file which includes your header. If more than one file includes the header or (as in your source file) any other file defines a variable with the same name, you'll get linker errors.
To fix this, change your header to declare the variable only
#ifndef worldActions_h
#define worldActions_h
extern bool worldAction;
#endif /* defined(__Julian_Story__worldActions__) */
and define/initialise it in your source file
#include <iostream>
#include "worldActions.h"
using namespace std;
bool worldAction = true;
use keyword externlike extern bool worldAction; & put definition bool worldAction = true in .cpp file
This question already has answers here:
How do I create a header-only library?
(4 answers)
Closed 9 years ago.
In a file called gl_ext.h I have the following:
#ifndef GLEXT_H_INCLUDED
#define GLEXT_H_INCLUDED
#include <stdexcept>
#ifdef WIN32
#include <Windows.h>
#include <GL/GL.h>
#include <GL/glext.h>
# define glGetProcAddress(arg) wglGetProcAddress(arg)
#elif __linux__
#include <GL/gl.h>
#include <GL/glext.h>
# include <GL/glx.h>
# define glGetProcAddress(arg) glXGetProcAddress((const GLubyte*)arg)
#endif
PFNGLCREATESHADERPROC glCreateShader = 0;
namespace glext
{
bool load_gl_extensions()
{
static bool loaded = false;
if (loaded) {
return true;
}
if (!glCreateShader) {
glCreateShader =
(PFNGLCREATESHADERPROC)(glGetProcAddress("glCreateShader"));
if (!glCreateShader) {
throw "Failed to load glCreateShader";
}
}
}
}
#endif
When building from within qt creator using the following .pro file
QT += core gui opengl
TEMPLATE = app
TARGET = GLExtensions
INCLUDEPATH += .
LIBS += -lGL
HEADERS += gl_ext.h \
qtrenderer.h
SOURCES += main.cpp \
qtrenderer.cpp
The usage of this "header library" is as follows:
main.cpp
#include <QtGui/QApplication>
#include "qtrenderer.h"
int main(int argc, char * argv[]) {
QApplication app(argc, argv);
QtRenderer *renderer = new QtRenderer();
renderer->show();
app.exec();
}
qtrenderer.h
#ifndef QTRENDERER_H_INCLUDED
#define QTRENDERER_H_INCLUDED
#include <QtCore/QObject>
#include <QtOpenGL/QGLWidget>
#include <gl_ext.h>
class QtRenderer : public QGLWidget
{
Q_OBJECT
private:
QtRenderer(const QtRenderer &other);
QtRenderer &operator = (const QtRenderer &other);
protected:
virtual void paintGL();
virtual void initializeGL();
public:
QtRenderer();
~QtRenderer();
public slots:
virtual void updateGL();
};
#endif
qtrenderer.cpp
#include "qtrenderer.h"
QtRenderer::QtRenderer() :
QGLWidget() {
}
QtRenderer::~QtRenderer() {
}
void QtRenderer::initializeGL() {
try {
glext::load_gl_extensions();
} catch (...) {
throw std::runtime_error("Failed to load needed extensions.");
}
}
void QtRenderer::paintGL() {
swapBuffers();
}
void QtRenderer::updateGL() {
paintGL();
}
When building this source code using
gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)
I get the following build errors:
qtrenderer.o: In function `glext::load_gl_extensions()':
/home/mehoggan/Devel/test_gl/./gl_ext.h:28: multiple definition of `glCreateShader'
main.o:/home/mehoggan/Devel/test_gl/./gl_ext.h:28: first defined here
Why is this so?
Well, the header gl_ext.h is included multiple times. Remember that #include is like replacing the #include statement with the content of the file in a copy&paste manner.
You should put the implementation of load_gl_extensions() into a .cpp file, and put only the declaration into the header file.
gl_ext.h:
//...
extern PFNGLCREATESHADERPROC glCreateShader;
namespace glext
{
bool load_gl_extensions();
}
gl_ext.cpp:
#include "gl_ext.h"
PFNGLCREATESHADERPROC glCreateShader = 0;
namespace glext
{
bool load_gl_extensions()
{
static bool loaded = false;
if (loaded) {
return true;
}
if (!glCreateShader) {
glCreateShader =
(PFNGLCREATESHADERPROC)(glGetProcAddress("glCreateShader"));
if (!glCreateShader) {
throw "Failed to load glCreateShader";
}
}
}
}
extern tells the compiler that the variable/function pointer (glCreateShader) is placed in a different compilation unit (every .cpp file is compiled as a different unit). The linker then inserts the correct memory-adress of your variable. Maybe you should do some research on how C++ compilation and linkage works.
The solution to the problem consisted of making the method inlined and declaring the function pointer as static.