I´m writing the clsLog class:
// This is the main DLL file.
#include "stdafx.h"
#include <time.h>
#include <fstream>
#include <iostream>
#include <string>
#include "clsLog.h"
std::string m_strCurLogUser;
int m_iCurLogAction;
int m_iCurLogLevel;
std::ofstream m_oCurLogFile;
//
// LogInit
// Initilize the log parameters of the system.
// The FileName will be the file name that the system will log the messages (LOG.TXT is the default if no names are given).
// The DatabaseName and TableName specifies the database and table name to be used for log. The default is "LOG_DATABASE" and "LOG_TABLE"
// will be done.
// The Action shall be an OR with all the options. Att: If an option is giver (ex: Database) and an invalid name is given, then an error will occur.
//
// The default log level is zero (0). So every log with a level upper than that will be logged. A change to the level must be done
// using the SetLogLevel method.
//
// return = 0: Success
// 1: Failure
//
int LogInit (std::string FileName, // Initialize the log file/connection.
std::string DatabaseName, // Database name to connect to.
std::string TableName, // Table name to connect to.
std::string UserName, // User name to log into
int Action) // Action to be done.
{
//
// If the file is already open, someone is calling that function before closing the previous one. Error.
//
if (m_oCurLogFile.is_open ())
{
std::string msg;
msg = "LogInit called for " + FileName + " witout closing previous session. Error";
this->clsLog::Log (msg);
}
// Do some stuff
return 0;
}
//
// Log
// Logs the Message according to its Level.
//
// return = 0: Success
// 1: Failure
//
int Log (std::string Message, int Level) // Register a log according to the log state.
{
time_t now;
struct tm ptm;
char buffer [32];
//
// If the sent message level is below the current level, abort.
//
if (Level < m_iCurLogLevel)
return 1;
// Get the current date and time and convert it to the time structure (ptm)
now = time (NULL);
localtime_s (&ptm, &now);
//
// Format the time structure: DD/MM/AAAA HH:MM:SS)
strftime (buffer, 32, "%D/%M/%Y %H:%M:%S", &ptm);
// Check if needs to be logged on stdio
//
if ((m_iCurLogLevel & LOGACTION_STDOUT) == LOGACTION_STDOUT)
{
cout << buffer + " " + Message;
}
return 0;
}
I´m not being able to compile. I´m getting the following error at
this->clsLog::Log (msg);
C2227 error on left of '->Log' must point to a class/struct/union/generic type. Using VS2010, Win32 application.
Help appreciated.
Rds
I don't see any evidence that your functions are inside a class definition; therefore, as the error message says, there's no "this" pointer available. "This" is only available in the instance members of a class.
The this pointer is only valid inside a method that is a (non-static) member of a class or struct. There is no this for a plain function such as LogInit.
Related
I'am developping a C++ project on an ESP32.
I'd like to use esp_console + argtable3 (C libraries) in it.
I'm trying to use argtable3 in my members functions.
To do so, I'm creating callback functions to my members functions with a global pointer.
I'm sure my class is going to be instanced only once so I assume it's ok to create callback functions.
The problem is that argtable isn't giving me back the parameters entered by the user.
It checks for them successfully (number of args and their type) but the data it gives me back is random.
I've tested my code outside of members functions and it works well. But I want to use it inside members functions to access other parts of my object.
Here is my code :
// Pointer for my callback functions
MyClass * _callback;
struct arg_int *argInt;
struct arg_end *endPage;
// My callback function (GLOBAL)
int _setInt(int argc, char *argv[])
{
return _callback->setInt(argc, argv);
}
// Tab of struct for argtable lib (GLOBAL)
void *setInt_argtable[] =
{
argInt = arg_int1(NULL, NULL, "<0-12>", "Integer argument"),
endInt = arg_end(10)
};
// Function I'm calling back
int MyClass::setInt(int argc, char *argv[])
{
int nerrors = arg_parse(argc,argv,setInt_argtable);
if (nerrors > 0)
{
arg_print_errors(stdout, endPage, "myprog");
return 0;
}
printf("argc = %d\n", argc); // argc gives the correct number of args
printf("argv[0] = %s\n", argv[0]); // argv[0] gives the correct command name
printf("argv[1] = %s\n", argv[1]); // argv[1] gives the correct value
printf("argInt->ival[0] = %d\n", argInt->ival[0]); // argInt->ival[0] gives random value
return 0;
}
void MyClass::main(void)
{
// Callback pointer initialisation
_callback = this;
/* Initializing the console */
esp_console_config_t console_config
{
256,
8,
atoi(LOG_COLOR_CYAN),
0
};
ESP_ERROR_CHECK( esp_console_init(&console_config) );
/* Configure linenoise line completion library */
/* Enable multiline editing. If not set, long commands will scroll within
* single line.
*/
linenoiseSetMultiLine(1);
/* Tell linenoise where to get command completions and hints */
linenoiseSetCompletionCallback(&esp_console_get_completion);
linenoiseSetHintsCallback((linenoiseHintsCallback*) &esp_console_get_hint);
/* Set command history size */
linenoiseHistorySetMaxLen(100);
esp_console_register_help_command();
//
// Feeding my console with argtable parameters
//
esp_console_cmd_t consoleCmd;
consoleCmd.command = "setInt";
consoleCmd.func = &_setInt;
consoleCmd.help = "Trying to set a integer argument";
consoleCmd.argtable = setInt_argtable;
esp_console_cmd_register(&consoleCmd);
/* Main loop */
while(true)
{
// Getting command from user
}
}
Is my approach of using callback member function good ?
Any idea of what is my problem and how I could solve it ?
Thanks in advance for your answers.
After being copying/pasting very simple sample codes found on internet, I finally found what was the problem :
I was including <argtable3/argtable3.h> after "myclass.h"
It took me almost 2 days for a dumb error...
But if somebody has an explanation about why the inclusion order was allowing me to compile the program but making a "corrupted" binary, feel free to answer !
I don't have enough reputation points to comment to ask if they solved the problem originally stated here. I have the same problem of the program crashing in construction of an ofstream.
It is not multi-threaded access, but it can be called in quick succession. I believe it crashes on the 2nd time. I use scope to ensure the stream object is destroyed.
Why would this happen?
I tried std::fopen too. It also results in a crash.
Here is the code using the ofstream:
static bool writeConfigFile (const char * filename, const Config & cfg)
{
logsPrintLine(_SLOG_SETCODE(_SLOGC_CONFIG, 0), _SLOG_INFO, "Write config file (%s stream)", filename);
ofstream os(filename); // FIXME: Crashes here creating ofstream 2nd time
if (os.good())
{
// Uses stream insertion operator to output attributes to stream
// in human readable form (about 2kb)
outputConfig(cfg, os);
if (!os.good())
{
logsPrintLine(_SLOG_SETCODE(_SLOGC_CONFIG, 0), _SLOG_NOTICE, "Failed to write configuration file (%s)", filename);
return false;
}
logsPrintLine(_SLOG_SETCODE(_SLOGC_CONFIG, 0), _SLOG_INFO, "Configuration written to file (%s)", filename);
return true;
}
logsPrintLine(_SLOG_SETCODE(_SLOGC_CONFIG, 0), _SLOG_NOTICE, "Cannot write configuration file (%s)", filename);
return false;
}
/**
* Called when configuration settings have been read/received and validated
* #return true if successfully set, and written to file
*/
bool Config::set (SysConfigSource source, const struct SCADA_dsconfig * p)
{
Lock lock(mtxSet); // This is locking a mutex on construction of the lock. Release it on destruction.
// Setup the non-current one to switch to
Config * pCfg = pConfig.other();
unsigned i, f, n = 0;
// set attributes in pCfg based on the config received
// and some constants ...
pCfg->setWritten(writeConfigFile("test.conf", *pCfg));
if (!pCfg->isWritten())
{
// Don't set system config status here. Existing one still in use.
logsPrintLine(_SLOG_SETCODE(_SLOGC_CONFIG, 0), _SLOG_NOTICE, "Config file not written. Retain prior config.");
return false;
}
pConfig.swap(); // switch-in the new config
setSystemConfigSource(source);
toSyslog(pCfg);
notifyConfigChange();
return true;
}
Maybe post a segment of your source code in order to get an idea of where it went wrong.
Here is a very basic segment of code of how I would use fstream.. hope you will find it helpful.
#include <iostream>
#include <fstream>
#include <string>
int main() {
while (1) {
std::string testString;
std::ofstream outFile;
outFile.open("Test", std::ios_base::app); // Appends to file, does not delete existing code
std::cout << "Enter a string: ";
std::cin >> testString;
outFile << testString << std::endl;
outFile.close();
}
}
It turned out to be a device driver bus master issue. Add "ahci nobmstr" when launching devb-ahci.
Derived via http://www.qnx.com/developers/docs/qnxcar2/index.jsp?topic=%2Fcom.qnx.doc.neutrino.user_guide%2Ftopic%2Fhardware_Troubleshooting_devb-eide.html
I tried to compile the below code:
Here is the server.h code (https://codeshare.io/an3XW4)
///////////////HEADER FILES///////////////
#include <pthread.h>
#include "Server.h"
///////////////FUNCTIONS///////////////
/*Thread Main Function
Variable Definition:
-- thread_arguments: arguments which thread should be used
Return Value: NULL
*/
void *threadMain(void *thread_arguments){
int client_socket; //socket descriptor for client
//Guarantees that thread resources are deallocated upon return
pthread_detach(pthread_self());
//Pass the arguments
client_socket = ((THREAD_ARGUMENTS*)thread_arguments)->client_socket;
//Deallocate memory for argument
free(thread_arguments);
//Handle the client request
handleClientRequest(client_socket);
return (NULL);
}
THIS IS TIMEUTILITY.C, i dont understand much about C, im a programmer in java and more higher level languages of that sort.
///////////////HEADER FILES///////////////
#include <sys/stat.h>
#include <time.h>
#include "Server.h"
///////////////FUNCTIONS///////////////
/*Set Timer Function
Variable Definition:
-- timer: itimerval structure
-- type: timer type
-- interval_sec: it_interval seconds
-- interval_usec: it_interval microseconds
-- value_sec: it_value seconds
-- value_usec: it_value microseconds
Return value: NULL
*/
void setTimer( struct itimerval timer,
int type,
u_int32 interval_sec,
u_int32 interval_usec,
u_int32 value_sec,
u_int32 value_usec){
//Set the time out value
timer.it_interval.tv_sec = interval_sec;
timer.it_interval.tv_usec = interval_usec;
//Set the first time out value
timer.it_value.tv_sec = value_sec;
timer.it_value.tv_usec = value_usec;
//Set the timer
if (setitimer(type, &timer, NULL) != 0){
dieWithSystemMessage("setitimer() failed");
}
return;
}
/*Get GMT Time Function (including System time and File time)
Variable Definition:
-- url: the request url except domain name and port number
-- signal_value: signal that decide which kind of time needed
Return value: tm struct in GMT Format
*/
struct tm *getTimeInGMTFormat(char *url, int signal_value){
struct stat file_information; //file information sstructure
time_t t; //time structure
//signal_value equals to 0, get the system current time
if (!signal_value){
time(&t);
}
//signal_value not equals to 0, get the file time(Create time, Modify time, Access time...)
else if (stat(url, &file_information) != -1){
switch(signal_value){
//signal_value is 1, get the file create time
case 1: t = file_information.st_atime; break;
//signal_value is 2, get the file modify time
case 2: t = file_information.st_mtime; break;
//signal_value is others
default: break;
}
}
//Cannot find the file information
else{
dieWithUserMessage("stat() failed(cannot find the file information), file name", url);
}
return gmtime(&t);
}
/*Convert Time Format to a string
Variable Definition:
-- gmt_time: tm struct in GMT format
-- signal_value: signal that decide which time format to convert
Return value: time string in GMT format
*/
char *convertTimeFormat(struct tm *gmt_time, int signal_value){
char *gmt_time_string = (char*)malloc(sizeof(char) * (TIME_SIZE + 1)); //time in GMT format string
//According to the signal_value, convert time to different format
switch(signal_value){
case 1:
strftime(gmt_time_string, TIME_SIZE, "%a, %d %b %Y %H:%M:%S GMT", gmt_time);
break;
case 2:
strftime(gmt_time_string, TIME_SIZE, "%A, %d-%b-%y %H:%M:%S GMT", gmt_time);
break;
case 3:
gmt_time_string = asctime(gmt_time);
gmt_time_string[strlen(gmt_time_string) - 1] = '\0';
break;
default:
break;
}
return gmt_time_string;
}
/*Compare the If-Modified-Since field and Last-Modified field Function
Variable Definition:
-- url: the request url except domain name and port number
-- modified_time_string: If-Modified-Since field value
Return Value: if If-Modified-Since field equals to Last-Modified field, return 1; else return 0
*/
bool compareModifiedTime(char *url, char *modified_time_string){
struct tm *file_modified_time = getTimeInGMTFormat(url, 2); //tm struct with the file last modified time
int i; //counter
//Test the modified time is equal(three format: RFC 1123, RFC 1036, and ANSI C's format)
for (i = 1; i < NUMBER_SIZE; i++){
if (strcmp(modified_time_string, convertTimeFormat(file_modified_time, i)) == 0){
return true;
}
}
return false;
}
But when I try to compile it, using g++ (C++ compiler) (the code was natively written in C), i get a weird error, anyone understand why? This is the full code of the Thread.C
/home/justin/Documents/dcn_streaming_video/server/Thread.c:23: multiple definition of `client_rtcp_port'
TimeUtility.o:/home/justin/Documents/dcn_streaming_video/server/TimeUtility.c:36: first defined here
Thread.o: In function `threadMain(void*)':
/home/justin/Documents/dcn_streaming_video/server/Thread.c:23: multiple definition of `client_rtp_port'
TimeUtility.o:/home/justin/Documents/dcn_streaming_video/server/TimeUtility.c:36: first defined here
Thread.o: In function `threadMain(void*)':
/home/justin/Documents/dcn_streaming_video/server/Thread.c:27: multiple definition of `range_end'
TimeUtility.o:/home/justin/Documents/dcn_streaming_video/server/TimeUtility.c:37: first defined here
Thread.o: In function `threadMain(void*)':
/home/justin/Documents/dcn_streaming_video/server/Thread.c:27: multiple definition of `range_start'
TimeUtility.o:/home/justin/Documents/dcn_streaming_video/server/TimeUtility.c:37: first defined here
Thread.o: In function `threadMain(void*)':
/home/justin/Documents/dcn_streaming_video/server/Thread.c:27: multiple definition of `status'
TimeUtility.o:/home/justin/Documents/dcn_streaming_video/server/TimeUtility.c:39: first defined here
Thread.o: In function `threadMain(void*)':
/home/justin/Documents/dcn_streaming_video/server/Thread.c:31: multiple definition of `session_id'
TimeUtility.o:/home/justin/Documents/dcn_streaming_video/server/TimeUtility.c:39: first defined here
Thread.o: In function `threadMain(void*)':
/home/justin/Documents/dcn_streaming_video/server/Thread.c:33: multiple definition of `rtp_address'
TimeUtility.o:/home/justin/Documents/dcn_streaming_video/server/TimeUtility.c:40: first defined here
Thread.o:(.bss+0x50): multiple definition of `protocol_method'
TimeUtility.o:/home/justin/Documents/dcn_streaming_video/server/TimeUtility.c:55: first defined here
Thread.o:(.bss+0x60): multiple definition of `protocol_type'
TimeUtility.o:/home/justin/Documents/dcn_streaming_video/server/TimeUtility.c:60: first defined here
As others have indicated, I do not see the whole source code, specifically, the Server.h which probably does not use multiple inclusion guards (i.e top level ifdef or pragma once).
I'm having an issue where I send a message to user-mode from kernel-mode using FltSendMessage that expects a reply. The struct being passed contains an int that is set to either 0 or 1. User-mode replies by setting this flag and calling FilterReplyMessage. However, when the message is received by the kernel, its value is always 56. No matter what number I set the flag to in user-mode, the kernel always receives the value 56. I'm confused as to where my error is.
I've tried changing the data type of passFlag from int to other types (USHORT etc..) which I knew probably wouldn't make a difference, but was worth a try.
Because the kernel message is replied to successfully (Checking user-mode HRESULT returns no errors and there is no timeout so if no reply is received the system would hang, which it does not), I know the error must be with the buffers being passed between user-mode and kernel-mode. I can't seem to find the reason why the passFlag is not being interpreted correctly in kernel-mode.
Can anyone help?
Shared Structure:
typedef struct _REPLY_MESSAGE_STRUCT {
// Message header.
FILTER_REPLY_HEADER header;
// Flag to be set
// by user mode.
int passFlag;
}REPLY_MESSAGE_STRUCT, *PREPLY_MESSAGE_STRUCT;
Kernel Code:
DbgPrint("Sending Message...\n");
replyBuffer.passFlag = 0;
ULONG replySize = ((ULONG)sizeof(replyBuffer.header)) + ((ULONG)sizeof(replyBuffer));
REPLY_MESSAGE_STRUCT replyBuffer;
// Note: Try-catch statement has been omitted in this question to save time.
// In the actual code there is a try-catch statement surrounding FltSendMessage.
status = FltSendMessage(imageFilterData.filterHandle,
&imageFilterData.clientPort,
(PVOID)&sendingBuffer.messageBuffer,
sizeof(sendingBuffer.messageBuffer),
(PVOID)&replyBuffer,
&replySize,
0
);
// Always returns 56
// When a reply has been received.
DbgPrint("Message received: %i\n", replyBuffer.passFlag);
User code:
// User-mode buffer is the same size as kernel-mode buffer.
ULONG replySize = ((ULONG)sizeof(replyBuffer.header)) + ((ULONG)sizeof(replyBuffer));
replyMessage.header.MessageId = messageFromKernel.header.MessageId;
REPLY_MESSAGE_STRUCT replyMessage;
// User-mode setting flag.
replyMessage.passFlag = 1;
// Flag is changed to 1 successfully.
printf("Test: %i\n", replyMessage.passFlag);
// Reply is sent successfully, but flag value on kernel end is always 56
hResult = FilterReplyMessage(port,
&replyMessage.header,
replySize);
_com_error err2(hResult);
errorMessage = err2.ErrorMessage();
// No errors.
printf("Result: %s\n", errorMessage);
What I have tried:
Changing the datatype of passFlag.
Going through every step before and after FltSendMessage and FilterReply message to find if the value is being changed before being sent back to the kernel.
you are using error data in call FltSendMessage:
ReplyBuffer is pointer to custom user defined data. it must not begin from FILTER_REPLY_HEADER
SenderBuffer is pointer to custom user defined data. it must not begin from FILTER_MESSAGE_HEADER
first of all you need define structures, that are shared between kernel and user mode, for message and reply. for example
struct SCANNER_NOTIFICATION {
// any custom data
int someData;
};
struct SCANNER_REPLY {
// any custom data
int passFlag;
};
and in kernel mode you direct use it as is:
SCANNER_NOTIFICATION send;
SCANNER_REPLY reply;
ULONG ReplyLength = sizeof(reply);
FltSendMessage(*, *, &send, sizeof(send), &reply, &ReplyLength, *);
in user mode you need define 2 additional structures:
struct SCANNER_MESSAGE : public FILTER_MESSAGE_HEADER, public SCANNER_NOTIFICATION {};
struct SCANNER_REPLY_MESSAGE : public FILTER_REPLY_HEADER, public SCANNER_REPLY {};
(i use c++ style here, when here used c style)
and in user mode we need use next, for example:
SCANNER_MESSAGE* mesage;
FilterGetMessage(*, mesage, sizeof(SCANNER_MESSAGE), *);
and
SCANNER_REPLY_MESSAGE reply;
reply.MessageId = mesage->MessageId;
FilterReplyMessage(*, &reply, sizeof(reply));
Here is the code that I use to play around with. I want to make this code can accept parameter from the console.
Now I can only run the code with hardcoded parameter. At the console I just type Example1Client.exe and press Enter.
I would like to send parameter like this: Example1Client.exe http://www.website.com
int main()
{
RPC_STATUS status;
unsigned char* szStringBinding = NULL;
// Creates a string binding handle.
// This function is nothing more than a printf.
// Connection is not done here.
status = RpcStringBindingCompose(
NULL, // UUID to bind to.
reinterpret_cast<unsigned char*>("ncacn_ip_tcp"), // Use TCP/IP
// protocol.
reinterpret_cast<unsigned char*>("localhost"), // TCP/IP network
// address to use.
reinterpret_cast<unsigned char*>("4747"), // TCP/IP port to use.
NULL, // Protocol dependent network options to use.
&szStringBinding); // String binding output.
if (status)
exit(status);
// Validates the format of the string binding handle and converts
// it to a binding handle.
// Connection is not done here either.
status = RpcBindingFromStringBinding(
szStringBinding, // The string binding to validate.
&hExample1Binding); // Put the result in the implicit binding
// handle defined in the IDL file.
if (status)
exit(status);
RpcTryExcept
{
visit("http://www.facebook.com");
openNew("http://www.yahoo.com");
}
RpcExcept(1)
{
std::cerr << "Runtime reported exception " << RpcExceptionCode()
<< std::endl;
}
RpcEndExcept
// Free the memory allocated by a string.
status = RpcStringFree(
&szStringBinding); // String to be freed.
if (status)
exit(status);
// Releases binding handle resources and disconnects from the server.
status = RpcBindingFree(
&hExample1Binding); // Frees the implicit binding handle defined in
// the IDL file.
if (status)
exit(status);
}
// Memory allocation function for RPC.
// The runtime uses these two functions for allocating/deallocating
// enough memory to pass the string to the server.
void* __RPC_USER midl_user_allocate(size_t size)
{
return malloc(size);
}
// Memory deallocation function for RPC.
void __RPC_USER midl_user_free(void* p)
{
free(p);
}
Modify definition of your main to: int main(int argc, char *argv[]) instead of int main().
Inside the main then, you can have the code as follows:
std::string url = "some default url";
if (argc > 1) {
url = argv[1];
}
Similar question(s) on Stackoverflow:
Passing filename as arguments in C
Passing command line arguments