Im trying to get rid of a platform dependent code.
This code gets a string formated by a mask ("%Y-%m-%d %H:%M:%S") and convert it to std::tm struct and a std::time seconds.
I want to get rid of the need of preprocessor dependant blocks, as (imho) there must be a standard way of doing it in both platforms in the same way.
strptime does not exists in windows, std::get_time does not exists(?) on linux (g++ c++11).
Is there any way to make this code crossplatform (windows/linux) without using a factory pattern or preprocessor dependant blocks?
KDATETIME& KDATETIME::operator= (const char* k)
{
std::string smask;
smask = (std::string)this->mask;
std::string sk;
sk=k;
tm.tm_isdst=-1;
#ifdef WINDOWS <<---- THIS BLOCK
std::istringstream ss(sk);
ss >> std::get_time(&tm, smask.c_str());
#else
strptime(sk.c_str(), smask.c_str(), &tm);
#endif <<------
this->time = mktime(&tm); // t is now your desired time_t
[...]
}
Related
I would like to program in threading building blocks with tasks. But how does one do the debugging in practice?
In general the print method is a solid technique for debugging programs.
In my experience with MPI parallelization, the right way to do logging is that each thread print its debugging information in its own file (say "debug_irank" with irank the rank in the MPI_COMM_WORLD) so that the logical errors can be found.
How can something similar be achieved with TBB? It is not clear how to access the thread number in the thread pool as this is obviously something internal to tbb.
Alternatively, one could add an additional index specifying the rank when a task is generated but this makes the code rather complicated since the whole program has to take care of that.
First, get the program working with 1 thread. To do this, construct a task_scheduler_init as the first thing in main, like this:
#include "tbb/tbb.h"
int main() {
tbb::task_scheduler_init init(1);
...
}
Be sure to compile with the macro TBB_USE_DEBUG set to 1 so that TBB's checking will be enabled.
If the single-threaded version works, but the multi-threaded version does not, consider using Intel Inspector to spot race conditions. Be sure to compile with TBB_USE_THREADING_TOOLS so that Inspector gets enough information.
Otherwise, I usually first start by adding assertions, because the machine can check assertions much faster than I can read log messages. If I am really puzzled about why an assertion is failing, I use printfs and task ids (not thread ids). Easiest way to create a task id is to allocate one by post-incrementing a tbb::atomic<size_t> and storing the result in the task.
If I'm having a really bad day and the printfs are changing program behavior so that the error does not show up, I use "delayed printfs". Stuff the printf arguments in a circular buffer, and run printf on the records later after the failure is detected. Typically for the buffer, I use an array of structs containing the format string and a few word-size values, and make the array size a power of two. Then an atomic increment and mask suffices to allocate slots. E.g., something like this:
const size_t bufSize = 1024;
struct record {
const char* format;
void *arg0, *arg1;
};
tbb::atomic<size_t> head;
record buf[bufSize];
void recf(const char* fmt, void* a, void* b) {
record* r = &buf[head++ & bufSize-1];
r->format = fmt;
r->arg0 = a;
r->arg1 = b;
}
void recf(const char* fmt, int a, int b) {
record* r = &buf[head++ & bufSize-1];
r->format = fmt;
r->arg0 = (void*)a;
r->arg1 = (void*)b;
}
The two recf routines record the format and the values. The casting is somewhat abusive, but on most architectures you can print the record correctly in practice with printf(r->format, r->arg0, r->arg1) even if the the 2nd overload of recf created the record.
~
~
Im writing a shared library for a FreeBSD application.
This library gets loaded by LD_PRELOAD.
This application has multiple compile-versions, so some function offsets might change and my library wont work there.
Now i want to read the offsets at loading the library.
The offsets are changing, so i think my only way is to read the offsets of specific function names.
The offsets are simply the offsets of functions or labels.
Now the problem - how to do it?
Example
In the first version, i call the main version like that:
int(*main)(int argc, char *argv[])=(int(*)(int,char*[]))0x081F3XXX;
but in the second, the offset has changed:
int(*main)(int argc, char *argv[])=(int(*)(int,char*[]))0x08233XXX;
Programmers (me) are lazy and don't want to compile their libs for every version.. I want to create a lib, that is for every version!
I simply need the offsets of the functions via function name, the rest is no problem..
Thats how i call the library:
LD_PRELOAD="/path/to/library.so" ./executable
or
env LD_PRELOAD="/path/to/library.so" ./executable
Edit with test code
Here my testcode regarding to the comments:
Main.cpp:
#include <stdio.h>
void test() {
printf("Test done.\n");
}
int main(int argc, char * argv[]) {
printf("Program started\n");
test();
}
lib.cpp
#include <stdio.h>
#include <dlfcn.h>
void __attribute__ ((constructor)) my_load(void);
void my_load(void) {
printf("Library loaded\n");
printf("test - offset: 0x%x\n",dlsym(NULL,"test"));
}
test.sh
g++ main.cpp -o program
g++ -shared lib.cpp -o lib.so
env LD_PRELOAD="lib.so" ./program
-> Result:
Library loaded
test - offset: 0x0
Program started
Test done.
Does not seem as would it work :s
Edit 15:45
printf("test - offset: 0x%x\n",dlsym(dlopen("/home/test/test_proc/program",RTLD_GLOBAL),"test"));
This also does not work.. Maybe dlsym is the wrong way?
I reproduced your program on Mac OS X using Clang, and found a solution. First, the boring parts:
To make it compile cleanly I had to change your %x format specifier to %p for the pointer.
Then, on Mac OS X I had to pass RTLD_MAIN_ONLY as the first argument to dlsym(). I guess this is platform-dependent; on Linux it does seem to be NULL as you have.
Now, the meat of the fix!
You're searching with dlsym() for a symbol called test. But there is no such symbol in your application. Why? Because you're using C++, and C++ does "name mangling." You could use any number of tools to figure out the mangled name and try to load that with dlsym(), but it could change with different compilers. So instead, just inhibit name mangling by enclosing your test() function in extern "C":
extern "C" {
void test() {
printf("Test done.\n");
}
}
This fixed it for me:
$ DYLD_INSERT_LIBRARIES=lib.so ./program
Library loaded
test - offset: 0x1027d1eb0
Program started
Test done.
I have a very strange problem with a sketch which performs differently if compiled and uploaded to Arduino from Windows XP Home sp3 or Elementary OS Luna (a distro of Ubuntu Linux).
This sketch, between other things, reads a byte from a serial connection (bluetooth) and write it back to serial monitor.
This is what I get if I compile the sketch from WinXP: I sent over BT connection strings from "1" to "7" one time each. The ASCII code of these strings are reduced of 48 to transform string in byte. The result is correct, also functions in pointer array are correctly called.
and here is what I get from Linux. I sent 4 times each string from "1" to "7" to see that result has nothing to do with what I need to get and also is not consistent with the same input data: for example when I send string "2" I get 104 106 106 104..... and same byte 106 is written with different Strings coming from BT.
Also the functions are not called so it means that is not a Serial.print issue.
I'm sure it is a compiling issue because once the sketch is uploaded in Arduino it performs in the same way (correct or not) if I use serial monitor in WinXP or Linux.
Here's the sketch
#include "Arduino.h"
#include <SoftwareSerial.h>
#include <Streaming.h>
#define nrOfCommands 10
typedef void (* CmdFuncPtr) (); // this is a typedef to command functions
//the following declares an arry of 10 function pointers of type DigitFuncPtr
CmdFuncPtr setOfCmds[nrOfCommands] = {
noOp,
leftWindowDown,
leftWindowUp,
bootOpen,
cabinLightOn,
cabinLightOff,
lockOn,
lockOff,
canStart,
canStop
};
#define cmdLeftWindowDown 1
#define cmdLeftWindowUp 2
#define cmdBootOpen 3
#define cmdCabinLightOn 4
#define cmdCabinLightOff 5
#define cmdLockOn 6
#define cmdLockOff 7
#define cmdCanStart 8
#define cmdCanStop 9
#define buttonPin 4 // the number of the pushbutton pin
#define bluetoothTx 2
#define bluetoothRx 3
int buttonState = 0; // variable for reading the pushbutton status
int androidSwitch=0;
byte incomingByte; // incoming data
byte msg[12];
byte msgLen=0;
byte msgIdMsb=0;
byte msgIdLsb=0;
//const byte cmdLeftWindowDown;
SoftwareSerial bluetooth(bluetoothTx,bluetoothRx);
void setup()
{
//Setup usb serial connection to computer
Serial.begin(115200);
//Setup Bluetooth serial connection to android
bluetooth.begin(115200);
//bluetooth.print("$$$");
randomSeed(analogRead(10));
delay(100);
//bluetooth.println("U,9600,E");
//bluetooth.begin(9600);
//time=0;
}
void loop() {
msgIdLsb=random(1,255);
msgIdMsb=random(0,5);
msg[0]=msgIdMsb;
msg[1]=msgIdLsb;
msgLen=random(9);
msg[2]=msgLen;
for (int x=3;x<msgLen+3;x++) {
msg[x]=random(255);
}
for (int x=3+msgLen;x<11;x++) {
msg[x]=0;
}
msg[11]='\n';
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
if ((buttonState == HIGH)||(androidSwitch==HIGH)) {
for (int x=0;x<12;x++) {
Serial<<msg[x]<<" ";
bluetooth.write(uint8_t(msg[x]));
}
Serial<<endl;
}
//Read from bluetooth and write to usb serial
if(bluetooth.available())
{
incomingByte = bluetooth.read()-48;
Serial<<incomingByte<<endl;
if (incomingByte<nrOfCommands)
setOfCmds[incomingByte]();
}
delay(10);
}
void noOp(void)
{
Serial<<"noOp"<<endl;
};
void leftWindowDown(void)
{
Serial<<"leftWindowDown"<<endl;
};
void leftWindowUp(void)
{
Serial<<"leftWindowUp"<<endl;
};
void bootOpen(void)
{
Serial<<"bootOpen"<<endl;
};
void cabinLightOn(void)
{
Serial<<"cabinLightOn"<<endl;
};
void cabinLightOff(void)
{
Serial<<"cabinLightOff"<<endl;
};
void lockOn(void)
{
Serial<<"lockOn"<<endl;
};
void lockOff(void)
{
Serial<<"lockOff"<<endl;
};
void canStart(void)
{
androidSwitch=HIGH;
};
void canStop(void)
{
androidSwitch=LOW;
};
Any help would be very helpful.
Thanks in advance.
I suppose you are using the arduino ide; if not, some of the following might not apply.
First, find out the location of the build directory the ide is using when it compiles and links the code. [One way to find out is to temporarily turn on Verbose output during compilation. (Click File, Preferences, "Show verbose output during compilation".) Click the Verify button to compile the code, and look at the path following the -o option in the first line of output.] For example, on a Linux system the build directory path might be something like /tmp/build3877126492387157498.tmp. In that directory, look for the .cpp file created during compilation.
After you find the .cpp files for your sketch on both systems, copy them onto one system so you can compare them and check for differences. If they are different, one or the other ide might be corrupt or an incorrect include might be occurring.
If the .cpp files differ, compare the compile flags, the header files, etc. I think the flags and AVR header files should be the same on both systems, with the possible exception that MSW files might have carriage return characters after the newline characters. Also check the gcc versions. [I don't have an MSW system to try, but I'm supposing that gcc is used on both systems for AVR cross-compiling. Please correct me if I'm wrong.]
If the .cpp files match, then test the generated binary files to find out where they differ. (For example, if the sketch file is Blink21x.ino, binary files might be Blink21x.cpp.elf or Blink21x.cpp.hex.) If you have a .elf file on both systems [I don't know if the MSW system will generate .elf] use avr-objdump on the Linux system to produce a disassembled version of code:
avr-objdump -d Blink21x.cpp.elf > Blink21x.cpp.lst
Then use diff to locate differences between the two disassembly files. Enough information is available in the .lst file to identify your source line if the difference is due to how your source was compiled, as opposed to a difference in libraries. (In the latter case, enough information is given in the .lst file to identify which library routines differ.)
If you don't have an .elf file on the MSW system, you might try comparing the .hex files. From the location of the difference you can find the relevant line in the Linux-system .elf-disassembly file, and from that can identify a line of your code or a library routine.
Years ago, I used to do some basic programming in C. Now I am attempting to relearn what I have forgotten as well as learn Visual C++. I am confused though by all the string options and now the extra layer of trying to make my programs Unicode compatible. I have been reading Beginning Visual C++ 2010 as well as online reading to learn this information.
As an exercise I am writing a very basic program that asks a user to input some text and then display that text in the form of a messagebox. The program works, but my way of getting it to work was more through guesswork and looking at other examples than truly understanding why I need to convert the various strings into different types.
The code is:
#include "stdafx.h"
#include <iostream>
#include <string>
#include "Windows.h"
using std::wcin;
using std::wcout;
using std::wstring;
int _tmain(int argc, _TCHAR* argv[])
{
wstring myInput;
wcout << "Enter a string: ";
getline(wcin, myInput);
MessageBoxW(NULL, myInput.c_str(), _T("Test MessageBox"), 64);
return 0;
}
The MessageBox syntax is:
int WINAPI MessageBox(
__in_opt HWND hWnd,
__in_opt LPCTSTR lpText,
__in_opt LPCTSTR lpCaption,
__in UINT uType
);
On the other hand, if I just use the command line argument as the text of the messagebox, I do not need to convert the string at all and I am not sure why.
#include "stdafx.h"
#include <iostream>
#include <string>
#include "Windows.h"
using std::wcout;
int _tmain(int argc, _TCHAR* argv[])
{
MessageBoxW(NULL, argv[1], _T("Test MessageBox"), 64);
return 0;
}
My confusion is:
Why do I need to use the c_str() for argument 2 to MessageBoxW and why do I need to use the _T() macro (?) in argument 3?
Why did the program work in the second code example without doing some sort of conversion?
What exactly does LPCTSTR mean? I see another variant in MSDN functions called LPTSTR.
Thanks!
1) .c_str() is a standard C++ method to convert from C++ strings to C strings. _tmain, _T('x'), _T("text") and _TCHAR are (somewhat ugly) Microsoft macros that make your program compile either in unicode or non-unicode mode. There's a global setting in the project options that set some macros to configure your project in one of these two modes.
If you are in non-unicode mode (referred to as ANSI mode in MS's documentation) the macros expand to:
main, 'x', "text", char
If you are in unicode mode, the macros expand to
wmain, L'x', L"text", wchar_t
2) and 3) Windows headers are full of typedefs and macros like that. Sometimes they make code more obscure thant it needs to be. In general, LP means pointer (long pointer, i guess, but it's been a while since we needed to distinguish between near and far pointers), C means "const", T means that it will be either char or wchar_t depending on project settings and STR is obviously "string". After all, it's a plain C type, that's why you can pass C strings to them without conversion.
The MessageBoxW function is expecting a C-style wide-character string (WCHAR ). The macro _L() alters your string so that it's Unicode compatible (WCHAR instead of char*).
argv[] doesn't do objects, so you're already getting a WCHAR pointer out of it.
LPCTSTR is basically a WINAPI typedef for const char * or const WCHAR*, depending on whether you are building as UNICODE. Also see this post: LPCSTR, LPCTSTR and LPTSTR
In short, your main function is being passed WCHAR* strings and MessageBoxW expects WCHAR* strings.
I am wanting to have a place where i can store all the strings used in my applicaton, so i can modify them in one place and not all the places. Something like a resource file, where i can put a label on the strings and just call the label.
I am not aware of anything offered by QT for this, so would I just need to create a header file with all those strings and include it everywhere I need it? What is the appropriate way to do this and could you offer a small example?
Thanks!!
I haven't used it yet, but I think, that the Qt Internationalization would allow you to do something like this, since one of it's options is to take all strings out of the application code so they can be replaced by translations. Even if you don't want to use any other features of this module, it would allow you to solve your problem. Replacing a string for a label would look like this:
QLabel *label = new QLabel(tr("Password:"));
The tr() function is already part of the Qt classes and you get a few more functions and macros for free that help to search and replace strings.
The strings to be replaced can then be managed with QtLinguist.
You can find a more detailed explanation here: Internationalization with Qt
In the old days[1], when using Windows resources, people have been using:
// in your project_strings.h file
#define STRING_PASSWORD 1
...
// resources project.rc
#include "project_strings.h"
STRINGTABLE
BEGIN
STRING_PASSWORD "Password:"
...
END
// in some other file
#include "project_strings.h"
CString str(STRING_PASSWORD);
The CString knew about windows resources (ugly dependency) and could go and read the string password. The #define is definitively very ugly in modern C++, but resources would not understand a static const variable or an inline function.
The easiest way to replicate this in a somewhat similar way is to use a header file with string declarations and then reference those strings anywhere you need them.
// in your project_strings.h
namespace MyProjectStrings {
const char *password;
...
}
// the project_strings.cpp for the strings
#include "project_strings.h"
namespace MyProjectStrings {
const char *password = "Password:";
...
}
// some random user who needs that string
#include "project_strings.h"
std::string password(MyProjectStrings::password);
Now all your strings are in project_strings.cpp and you cannot as easily translate them with tr()... but you could transform all those strings declarations with functions:
// in your project_strings.h
namespace MyProjectStrings {
const char *password(); //[2]
...
}
// the project_strings.cpp for the strings
#include "project_strings.h"
namespace MyProjectStrings {
const char *password() { return QObject::tr("Password:"); }
...
}
// some random user who needs that string
#include "project_strings.h"
std::string password(MyProjectStrings::password()); //[3]
And VoilĂ ! You have a single long table of all your strings in one place and translatable.
[1] Many people still use that scheme!
[2] The function could return std::string to 100% prevent modifying the original.
[3] In this last example the string reference uses () since it's a function call.