How to use of code chunks as parameters to c preprocessor directives? - metaprogramming

Is there a way to provide a macro with entire chunks of code as a parameter and expand it into the definition?
#define PATTERN(param,func)\
chk=new wxCheckBox(page,wxID_ANY,param);\
sizer->Add(chk,0,0,0);\
chk->Bind(wxEVT_CHECKBOX,func);
PATTERN("checkbox 1",
//piece of code
[=](wxCommandEvent& event){
wxMessageBox(wxT("test"),wxT(""),wxICON_INFORMATION);
}
//end of code
)
How to encapsulate code for these means?
I want to be able to do:
#define DERIVATIVE(s)\
PATTERN(...)

You're better off using two sets of macros for this
#define TEMPLATE_CODE(INSERTME) \
... \
INSERTME(); \
...
#define SPECIALIZED_CODE() \
...
TEMPLATE_CODE(SPECIALIZED_CODE);
As an example,
#define TEMPLATE_CODE(INSERTME, ARG) void sayhello(void) { INSERTME(ARG); }
#define OTHER_TEMPLATE(INSERTME, ARG) class myclass { INSERTME(ARG); }
#define FIRST_IMPL(ARG) cout << ARG << endl
#define WRAPPER() TEMPLATE_CODE(FIRST_IMPL, ARG)
OTHER_TEMPLATE(WRAPPER, "hello world")
#undef FIRST_IMPL
#undef WRAPPER

Related

How to make a simple structure visible in different cpp file

I have a structure defined in main.cpp file and i want that same structure with value to be visible in other cpp file.
I tried this and this is way out of understanding for me as a beginner. So i re-ask the initial question again but in a simple way.
main.cpp
#include<iostream>
extern struct abc
{
int a;
std::string bla_bla;
};
void display(abc (&)[2]);
int main(void)
{
abc put[2];
put[0] = {10,"Apple"};
put[1] = {20,"Ball"};
display(put);
}
other.cpp
#include <iostream>
extern abc;
void display(abc (&put)[2])
{
std::cout << put[0].a << '\t' << put[0].bla_bla << std::endl;
std::cout << put[1].a << '\t' << put[1].bla_bla << std::endl;
}
it shows error a storage class can only be specified for objects and functions
and i am using c++17
is there any way to make that one structure visible to every cpp?
thanks in advance
EDIT: I got it need to keep the struct in .h file

How to print eight words to a line using vector<string>?

I was trying to make a program write 8 words to a line after a user enter their sentence.Its only printing words that have been typed in and i don't have a clue how to make it type 8 words to a line.
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
using namespace std;
vector<string> sentence;
string sente = "";
void print(string, string);
template<typename T>
void print(vector<T>& v, string)
{
cout << "Enter your sentence " << endl;
getline(cin, sente);
sentence.push_back(sente);
for (auto const elem: sentence)
{
cout << elem;
}
}
int main()
{
print(sentence,sente);
}
Using global variables is generally not a good practice.
Also you don't need a extra vector for your use case.
Take a look at the following code, where you can smartly make use of istringstream for your use case:
#include <iostream>
#include <string>
#include <sstream>
void print()
{
std::string sente;
std::cout << "Enter your sentence " << std::endl;
getline(std::cin, sente);
// Used to split string around spaces.
std::istringstream ss(sente);
int wordCountPerLine = 0;
int requiredWordsPerLine = 8;
// Traverse through all words
do {
// Read a word
std::string word;
ss >> word;
// Print the read word
std::cout << word << " ";
wordCountPerLine++;
if(wordCountPerLine % requiredWordsPerLine == 0){
std::cout<<std::endl;
wordCountPerLine = 0;
}
// While there is more to read
} while (ss);
}
int main()
{
print();
}
Feel free to ask any doubts.

C++ portability from Windows to Linux

I have been successfully using the following code in C++ on Windows (via CodeBlocks) and have recently attempted to use the same code on Linux (Ubuntu 18.04) also via CodeBlocks. The code appears to compile fine but fails on execution.
The purpose of the code is to import a comma delimited text file of numbers into an array.
In both Windows and Linux I am using the GNU GCC Compiler.
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <cmath>
#include <iomanip>
#include <ctime>
#include <cstdio>
#include <stdlib.h>
using namespace std;
typedef vector <double> record_t;
typedef vector <record_t> data_t;
istream& operator >> ( istream& ins, record_t& record)
{
record.clear();
string line;
getline( ins, line );
stringstream ss( line );
string field;
while (getline( ss, field, ',' ))
{
stringstream fs( field );
double f = 0.0;
fs >> f;
record.push_back( f );
}
return ins;
}
//-----------------------------------------------------------------------------
istream& operator >> ( istream& ins, data_t& data )
{
data.clear();
record_t record;
while (ins >> record)
{
data.push_back( record );
}
return ins;
}
//-----------------------------------------------------------------------------
int main()
{
data_t data;
ifstream infile( "Import File.txt" );
infile >> data;
if (!infile.eof())
{
cout << "Unsuccessful Import!\n";
return 1;
}
infile.close();
cout << "Your file contains " << data.size()-1 << " records.\n";
return 0;
}
I've checked that the necessary header files exist on Linux and that appears to be the case.
If I comment out the EOF check the console returns the message that
Process returned 49 (0x31)
A snippet of the import file which fails under Linux is:
1138,1139,1137.25,1138.5
1138.25,1138.75,1138.25,1138.5
1138.75,1139,1138.5,1138.75
1138.75,1138.75,1138.25,1138.25
1138.25,1138.25,1137.5,1137.5
1137.5,1138.75,1137.5,1138.5
1138.75,1143.75,1138.75,1143
1143.25,1145.75,1143.25,1144.5
1144.5,1144.75,1143,1143.25
1143.5,1144.5,1143.25,1144.25
Grateful for any help in finding a solution.
That return 4321; in main reports an unsuccessful return code to the OS. Only 0 return code (aka EXIT_SUCCESS) is considered successful.
Change it to return 0 or completely remove that return statement (in C++ main has implicit return 0).

Why some callback function can't be called in Pin?

I use the Intel-Pin to instrument pthread_mutex_lock and pthread_mutex_unlock in Linux. I insert functions before and after this two lock function's invocation respectively, so I expect that the tool will output strings before and after the lock functions. The instrument code is as follow
#include "pin.H"
#include <iostream>
#include <fstream>
/* ===================================================================== */
/* Names of pthread_mutex_lock and pthread_mutex_unlock */
/* ===================================================================== */
#define PTHREAD_MUTEX_INIT "pthread_mutex_init"
#define PTHREAD_MUTEX_DESTROY "pthread_mutex_destroy"
#define PTHREAD_MUTEX_LOCK "pthread_mutex_lock"
#define PTHREAD_MUTEX_UNLOCK "pthread_mutex_unlock"
/* ===================================================================== */
/* Global Variables */
/* ===================================================================== */
PIN_LOCK lock;
std::ofstream TraceFile;
/* ===================================================================== */
/* Commandline Switches */
/* ===================================================================== */
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
"o", "malloctrace.out", "specify trace file name");
/* ===================================================================== */
/* ===================================================================== */
/* Analysis routines */
/* ===================================================================== */
VOID Pthread_mutex_lock_callBefore( ADDRINT lockaddr)
{
PIN_GetLock(&lock, 1);
printf("Pthread_mutex_lock_callBefore\n");
PIN_ReleaseLock(&lock);
}
VOID Pthread_mutex_lock_callAfter(ADDRINT ret)
{
if(ret != 0)
return;
PIN_GetLock(&lock, 2);
printf("Pthread_mutex_lock_callAfter\n");
PIN_ReleaseLock(&lock);
}
VOID Pthread_mutex_unlock_callBefore(ADDRINT lockaddr)
{
PIN_GetLock(&lock, 3);
printf("Pthread_mutex_unlock_callBefore\n");
PIN_ReleaseLock(&lock);
}
static VOID Pthread_mutex_unlock_callAfter(ADDRINT ret)
{
if(ret != 0)
return;
PIN_GetLock(&lock, 4);
printf("Pthread_mutex_unlock_callAfter\n");
PIN_ReleaseLock(&lock);
}
/* ===================================================================== */
/* Instrumentation routines */
/* ===================================================================== */
VOID Image(IMG img, VOID *v)
{
RTN pmlRtn = RTN_FindByName(img, PTHREAD_MUTEX_LOCK);
if (RTN_Valid(pmlRtn) && PIN_IsApplicationThread() )
{
RTN_Open(pmlRtn);
RTN_InsertCall(pmlRtn, IPOINT_BEFORE, (AFUNPTR)Pthread_mutex_lock_callBefore,
IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
IARG_END);
RTN_InsertCall(pmlRtn, IPOINT_AFTER, (AFUNPTR)Pthread_mutex_lock_callAfter,
IARG_FUNCRET_EXITPOINT_VALUE,
IARG_END);
RTN_Close(pmlRtn);
}
//pthread_mutex_unlock
pmlRtn = RTN_FindByName(img, PTHREAD_MUTEX_UNLOCK);
if (RTN_Valid(pmlRtn) )
{
RTN_Open(pmlRtn);
RTN_InsertCall(pmlRtn, IPOINT_BEFORE, (AFUNPTR)Pthread_mutex_unlock_callBefore,
IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
IARG_END);
RTN_InsertCall(pmlRtn, IPOINT_AFTER, (AFUNPTR)Pthread_mutex_unlock_callAfter,
IARG_FUNCRET_EXITPOINT_VALUE,
IARG_END);
RTN_Close(pmlRtn);
}
}
/* ===================================================================== */
VOID Fini(INT32 code, VOID *v)
{
TraceFile.close();
}
/* ===================================================================== */
/* Print Help Message */
/* ===================================================================== */
INT32 Usage()
{
cerr << "This tool produces a trace of calls to malloc." << endl;
cerr << endl << KNOB_BASE::StringKnobSummary() << endl;
return -1;
}
/* ===================================================================== */
/* Main */
/* ===================================================================== */
int main(int argc, char *argv[])
{
// Initialize pin & symbol manager
PIN_InitLock(&lock);
PIN_InitSymbols();
if( PIN_Init(argc,argv) )
{
return Usage();
}
// Write to a file since cout and cerr maybe closed by the application
TraceFile.open(KnobOutputFile.Value().c_str());
TraceFile << hex;
TraceFile.setf(ios::showbase);
// Register Image to be called to instrument functions.
IMG_AddInstrumentFunction(Image, 0);
PIN_AddFiniFunction(Fini, 0);
// Never returns
PIN_StartProgram();
return 0;
}
/* ===================================================================== */
/* eof */
/* ===================================================================== */
compile this tool
make obj-ia32/mytool.so TARGET=ia32
use this tool to instrument a simple test
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
pthread_mutex_t m;
void * fun1(void *arg)
{
pthread_mutex_lock(&m);
pthread_mutex_unlock(&m);
}
int main(int argc,char* argv[])
{
pthread_t npid1;
pthread_mutex_init(&m,NULL);
pthread_create(&npid1,NULL,fun1,NULL);
pthread_join(npid1,NULL);
return 0;
}
compile this test
gcc -g t.c -o t -lpthread
At last, I use the my tool to instrument this test
sudo ./pin -t obj-ia32/mytool.so -- ./t
the result is
lab#lab:~/MyPinTool$ sudo ./pin -t obj-ia32/mytool.so -- ./t
Pthread_mutex_lock_callBefore
Pthread_mutex_lock_callAfter
Pthread_mutex_unlock_callBefore
Pthread_mutex_lock_callBefore
Pthread_mutex_lock_callAfter
Pthread_mutex_unlock_callBefore
Pthread_mutex_lock_callBefore
Pthread_mutex_lock_callAfter
Pthread_mutex_unlock_callBefore
You can see there is no Pthread_mutex_unlock_callAfter, I have insert a function after the pthread_mutex_unlock, why this function have not been callded? PS :the Pin API say that
VOID LEVEL_PINCLIENT::RTN_InsertCall ( RTN rtn,
IPOINT action,
AFUNPTR funptr,
...
)
Insert call relative to a rtn.
Parameters:
rtn Routine to instrument
action Use IPOINT_BEFORE to call funptr before execution, or IPOINT_AFTER for immediately before the return NOTE: IPOINT_AFTER is implemented by instrumenting each return instruction in a routine. Pin tries to find all return instructions, but success is not guaranteed
funptr Analysis function to call
... IARG_TYPE. Arguments to pass to funptr
As Nitzan said already, the APIs says it all: Pin tries to instrument each ret instruction of the function, but success is not garanteed. Think what would happen if an exception is thrown within the function, or if a long jump outside of the function happens...
There are many reasons for a function to be interrupted before reaching the return statement.

Passing objects as parameters by another object visual c++

I'm trying to pass an object by reference in c++. I get these errors:
Error 1 error C2061: syntax error : identifier 'Common' graphics.h 6 1 SDLGameDev
Error 2 error C2511: 'void Graphics::CreateWindow(Common &)' : overloaded member function not found in 'Graphics' 4 1 SDLGameDev
I found answers about this area, but not any that covers how to do this:
object1.someFunction(object2);
Here is my code:
//Common.h
#ifndef COMMON_H
#define COMMON_H
#include "SDL.h"
#include "iostream"
class Common{
public:
void Init();
bool GetGameRunState(){ return GameRunState; }
void SetGameRunState(bool x){ GameRunState = x; }
private:
bool GameRunState;
};
#endif
//Commmon.cpp
#include "Common.h"
void Common::Init()
{
if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
SetGameRunState(true);
}
else
{
SetGameRunState(false);
}
}
//Graphics.h
#ifndef GRAPHICS_H
#define GRAPHICS_H
class Graphics{
public:
void CreateWindow(Common & co);
};
#endif
//Graphics.cpp
#include "Graphics.h"
#include "Common.h"
void Graphics::CreateWindow(Common & co)
{
if (co.GetGameRunState() == true)
{
std::cout << "TEST for CreateWindow()\n";
}
}
//main.cpp
#include "Common.h"
#include "Graphics.h"
Common co;
Graphics go;
int main(int argc, char * args[])
{
co.Init();
go.CreateWindow(co);
while (co.GetGameRunState() == true)
{
std::cout << "Game is running\n";
SDL_Delay(2000);
break;
}
return 0;
}
You haven't included Common.h in the file Graphics.h so it doesn't know about the class.
#ifndef GRAPHICS_H
#define GRAPHICS_H
#include "Common.h" // You need this line
class Graphics {
public:
void CreateWindow(Common & co);
};
#endif
I would recommend using singletons and put the initialisation of sdl, creation of the renderer and window etc all together in one class. Your question has already been answered.

Resources