I know that C++ cannot create variables at runtime. Everything has to be declared when it is compiled.
My question is, if I have, let's say, 10 included header files with simple variable names, can I reference them dynamically, by the header file name or something like that.
For example, if I had two header files, one called "myVars1.h" with variable "myVars1name" and another called "myVars2.h" with a variable "myVars2name" could I do something like
int fileNum = 1;
string name = ["myVars" + fileNum + "name]; //i wish this worked...
Is this along the same lines as creating variables at runtime (and therefore illegal)?
Thanks
Assuming these variables are declared in header files, and defined somewhere else as global variables, you may get what you want by using dlsym(). Basically C/C++ cannot define variables at runtime, but it can load them at run time.
Precondition: these variables must be built into shared library, e.g. mylib.so
....
int fileNum = 1;
string name = ["myVars" + fileNum + "name]; //i wish this worked...
void *handle = dlopen("$PATH/mylib.so", RTLD_LAZY);
void *varPtr = dlsym(handle, name); // Your wish comes true here...
//cast varPtr to its target type.
....
I think you should use Namespaces
Related
I am having the problem, that my application can has a lot of user input which determines how the application will be run. The application is an in memory database system and the user could for example invoke the program with commands like '--pagesize 16384' (sets the memory page size to use), '--alignment 4096' (sets the memory alignment to use) or '--measure' (sets a flag to measure certain routines).
Currently I save all the user input in global variables which are defined as extern in a header file:
//#file common.hh
extern size_t PAGE_SIZE_GLOBAL;
extern size_t ALIGNMENT_GLOBAL;
extern size_t MEMCHUNK_SIZE_GLOBAL;
extern size_t RUNS_GLOBAL;
extern size_t VECTORIZE_SIZE_GLOBAL;
extern bool MEASURE_GLOBAL;
extern bool PRINT_GLOBAL;
extern const char* PATH_GLOBAL;
and in main source file:
#include "modes.hh"
size_t PAGE_SIZE_GLOBAL;
size_t ALIGNMENT_GLOBAL;
size_t MEMCHUNK_SIZE_GLOBAL;
size_t RUNS_GLOBAL;
size_t VECTORIZE_SIZE_GLOBAL;
bool MEASURE_GLOBAL;
bool PRINT_GLOBAL;
const char* PATH_GLOBAL;
int main(const int argc, const char* argv[]){
...
//Initialize the globals with user input
PAGE_SIZE_GLOBAL = lArgs.pageSize();
ALIGNMENT_GLOBAL = lArgs.alignment();
MEMCHUNK_SIZE_GLOBAL = lArgs.chunkSize();
RUNS_GLOBAL = lArgs.runs();
VECTORIZE_SIZE_GLOBAL = lArgs.vectorized();
MEASURE_GLOBAL = lArgs.measure();
PRINT_GLOBAL = lArgs.print();
std::string tmp = lArgs.path() + storageModel + "/";
PATH_GLOBAL = tmp.c_str();
...
}
I then include the header file common.hh in each file, where a global variable is needed (which can be very deep down in the system).
I already read a dozen times to prevent global variables so this is obviously bad style. In the book 'Code Complete 2' from Steve McConnell the chapter about global variables also stated to prevent global variables and use access routines instead. In the section 'How to Use Access Routines' he writes
"Hide data in a class. Declare that data by using the static keyword
(...) to ensure only a single instance of the data exists. Write
routines that let you look at the data and change it."
First of all, the global data won't change (maybe this is changed later but at least not in the near future). But I don't get how these access routines are any better? I will also have a class I need to include at every file where the data is needed. The only difference is the global data are static members accessed through getter functions.
(Edited) I also thought about using a global data Singleton class. But an object with ALL the global data sounds overkill since only a few global variables of the object are needed at its different destinations.
My Question: Should I just stick to the global variables? Are there better solutions, what am I missing? What are the best practices?
Edit:
If I would identify a few classes where the user input is needed the most, I could change the global data to member variables. What would be the best practice to pass the user input to these classes? Passing the data as parameters through the whole system down to the lowest layers sounds wrong. Is there are design pattern (thinking about something like a factory) which would be suited here?
How to pass user input through the system without using global
variables.
It is easy. Surprise, I created a class.
For a while, I called this class a travel case, because I considered it analogous to the needs of a suitcase during a trip. The TC_t is a non-standard container which held useful things for what is going on at your destination, and there is only one created, with references passed to any other objects that could use the information. Not global, in the strictest sense.
This TC_t is created in main() thread, while studying the command line options.
I recently wrote yet-another-game-of-life. User inputs included a) destination of output (i.e. a tty num), b) initial fill-pattern choices, c) 'overrides' for game board dimensions, d) test modes, including max speed, and vector vs. array options for cell behaviours.
The GOLUtil_t (Game Of Life Utility) (previously TC_t) includes methods that are useful in more than one effort.
For your question, the two typical globals I avoided are the a) gameBoard, and b) ansi terminal access.
std::cout << "accessing '" << aTermPFN << "' with std::ofstream "
<< std::endl;
std::ofstream* ansiTerm = new std::ofstream(aTermPFN);
if (!ansiTerm->is_open())
{
dtbAssert(nullptr != ansiTerm)(aTermPFN);
std::cerr << "Can not access '" << aTermPFN << "'" << std::endl;
assert(0); // abort
}
// create game-board - with a vector of cell*
CellVec_t gameBoard;
gameBoard.reserve (aMaxRow * aMaxCol);
GOLUtil_t gBrd(aMaxRow, aMaxCol, gameBoard, *ansiTerm);
This last line invoked the ctor of GOLUtil_t.
The instance "gBrd" is then passed (by reference) to the ctor of the game, and from there, to any aggregate objects it contained.
std::string retVal;
{
// initialize display, initialize pattern
GameOfLife_t GOL(gBrd, timeOfDay, fillPatternChoiceLetter, useArray);
std::string retValS = GOL.exec2(testMode);
retVal = gBrd.clearGameBoard(retValS); // delete all cells
}
// force GameOfLife_t dtor before close ansiTerm
ansiTerm->close();
Summary - No globals.
Every instance of any class that needed this info (where to output? what are dimensions?) has access to the GOLUtil_t for their entire lifetime. And GOLUtil_t has methods to lighten the coding load.
Note: because single output terminal, I used a single thread (main)
Your first refactor effort might be to:
a) remove the global classes,
b) and instead instantiate these in main() (for lifetime control)
c) and then pass-by-reference these formerly global instances to those non-global objects that make use of them. I recommend in the ctor(s).
d) remember to clean up (delete if new'd)
my environment: Ubuntu 15.10, 64 bit, g++ V5
I am experiencing the following issue, in my DLL project:
At the DLL side :
Inside the DLL I have declared a static vector as follows :
static std::vector<FilterProcessor::FilterInfo*> TableOfContents;
At DLL’s initialization time of static members, I am adding some entries to the above vector.
I have defined an extern “C” global function (getTocPointer()) which is returning a pointer to the vector, when it called from the client program.
extern "C" __declspec(dllexport) std::vector<FilterProcessor::FilterInfo*>* __cdecl getLibraryTOC();
At the client’s program side :
The DLL library is loaded without any problem
The address of getTocPointer() function is returned correctly to the client program, when the getProcAddress() function is called.
Indeed, when I am performing the debugging process in the DLL-side, the client program calls the above function and the execution process enters to it.
However, the vector has a zero size and, has no any contents which were added to it at initialization time. It seems it points to another vector object. . .
I can’t really understand what exactly goes wrong here.
The way of adding entries to this vector at initialization time, is the proper way?
If yes, what probably goes wrong when the client program calls the getLibraryTOC() function?
Thanks in advance
George
If that static global definition of the vector appears in a header file, then yes you do have multiple different vectors. Change the keyword static to extern to make the header file declare the vector rather than defining it, and then add exactly one definition in an implementation file.
Then, you may encounter the static initialization order fiasco. If the vector is defined in a different compilation unit than the code attempting to add entries to it, there's no guarantee that the vector object is alive yet. Attempting to use a vector whose constructor hasn't run is undefined behavior -- it might easily manifest as the constructor running afterward and setting the contents to zero length (as a default constructor should), but many other problems are possible.
You can avoid the SIOF by using a local static.
std::vector<FilterProcessor::FilterInfo*>& table_of_contents()
{
static std::vector<FilterProcessor::FilterInfo*> singleton;
return singleton;
}
In every location that would have accessed the global, including the initialization logic that fills the vector, and also your getLibraryTOC() exported function, call the accessor function instead.
That all is applicable to any C++ software having multiple compilation units. When you have a DLL, things get even more complicated, because the DLL and EXE are compiled and linked separately from each other, possibly with different settings, different compilers, or even entirely different languages. Sharing of complex objects across DLL boundaries is real trouble. If the DLL and EXE are always recompiled at the same time, it can work. But if you're trying to distribute the DLL for use by another party who writes the EXE code, the strong coupling will quickly become intolerable.
A better approach is to hide the library objects from the DLL boundary, and pass only primitive or OS-managed types across. For example:
#define DLLAPI __declspec(dllexport) __cdecl
extern "C" DLLAPI int32_t getLibraryTocCount()
{ return table_of_contents.size(); }
extern "C" DLLAPI BSTR getLibraryTocName(int index)
{ return ::SysAllocString(table_of_contents[index].name.c_str(); } // assumes std::wstring
// etc
The library I have implemented contains the following code (in a brief description) :
An Index class which implements the Table of contents of the library
A collection of audio filters named Filter01, Filter02 etc.
Index.h
struct LIB_SPECS Library_TableOfContents
{
static bool addTOCEntry(FilterInfo* Filter_Info); // add an entry to the TOC
static std::vector<FilterInfo*> TableOfContents; // TOC
};
/*-------------------------------------------------------------------
Called from the client program to return the pointer to TOC */
extern "C" LIB_SPECS std::vector<FlterInfo*>* __cdecl getLibraryTOC();
Index.cpp
/* Define / Initialize static variables */
std::vector<FilterInfo*> Library_TableOfContents::TableOfContents = {};
//=====================================================================
bool Library_TableOfContents::addTOCEntry(FilterInfo* Filter_Info)
{
Library_TableOfContents::TableOfContents.push_back(Filter_Info);
return false;
}
//======================================================================
std::vector<FilterInfo*>* getLibraryTOC()
{
return &Library_TableOfContents::TableOfContents;
}
For each Audio Filter in the library :
Filterxx.h
class LIB_SPECS Filterxx
{
public:
static struct FilterInfo
{
public:
std::string filterName;
std::string filterDescription;
// other filter info
FilterInfo(); // FilterInfo constructor
} Filter_Info;
virtual String doSomeWork(int AvatarId);
virtual void deleteFilter() = 0;
};
Filterxx.cpp
Filterxx::FilterInfo Filterxx::Filter_Info("Filterxx", “A filter description e.g. Low pass Filter ” ); //
FilterInfo::FilterInfo(std::string name, std::string description)
{
Filter_Info.filterName = name;
Filter_Info.filterDescription = description;
Library_TableOfContents::addTOCEntry(&Filter_Info);
}
// other filter functions
The getLibraryTOC() function, is called from the client program to get the table of contents in order to show it to the user.
As I said, indeed it is called by the client but, at the time of call, the table of contents seems to have a zero size.
I've got some problems with refering from 1 file to another.
I've got 2 VCL Forms:
- OpenPlotFile
- SelectElement
In my Plotfile I've got an openDialog:
void __fastcall TPlotFileForm::btn_fileselectClick(TObject *Sender)
{
AnsiString message;
//Dialog opties instellen
OpenDialog->Options << ofFileMustExist;
OpenDialog->Filter ="PPD files (*.PPD) |*.ppd |PLOT files (PLOT.*) | plot.*";
OpenDialog->FilterIndex = 2;
if (OpenDialog->Execute())
{
plotFile = OpenDialog->FileName;
Itxt_plotfile->Text=plotFile;
try
{
TFileStream *plotStream = new TFileStream(plotFile, fmOpenRead);
TStringStream *plotString = new TStringStream();
plotString->CopyFrom(plotStream, plotStream->Size);
FileBuffer = plotString->DataString;
delete plotStream;
delete plotString;
message = "Make your choice what to plot";
ListBox1->Items->Add(message);
message = "Default is everything, on insulation and with automatic weepholes at 1000 mm...";
ListBox1->Items->Add(message);
message = "Accept with the OK button...";
ListBox1->Items->Add(message);
btn_OK->Enabled=true;//Knop activeren nadat file is gekozen
}
catch(EStreamError &e)
{
ShowMessage(e.Message);
}
}
}
In this file I have a plotFile, this is the file directory. I want to get that value to another form: SelectElement
How I do it now is simple: I add AnsiString plotFile; to the OpenPlotFile.h
And I include OpenPlotFile.h in the SelectElement file.
#include "PlotFileScreen.h"
void __fastcall TSelectElementForm::FormShow(TObject *Sender)
{
element *ElementArray = new element[100];
ElementArray = GetElementInfo();
Itxt_plot_file->Text = plotFile;
Itxt_ordernumber->Text = ElementArray[0].ON;
Itxt_element_id->Text = ElementArray[0].MO;
Itxt_type->Text = ElementArray[0].SN;
Itxt_concrete->Text = ElementArray[0].el_concrete_height;
Itxt_Insulation->Text = ElementArray[0].el_iso_height;
Itxt_Length->Text = ElementArray[0].el_length;
Itxt_Width->Text = ElementArray[0].el_width;
Itxt_Weight->Text = ElementArray[0].el_weight;
Itxt_slabmark->Text = "";
Itxt_reinforce->Text = ElementArray[0].OW;
}
My program compiles and it works fine, but the odd thing is, When I debug, in both files it says: plotFile = NULL.
How can I solve this? Or how can I pass the plotFile to the other file without being NULL?
FYI: Global variables are ugly and should be avoided when possible. Encapsulation and abstraction are your friends. But to answer your question:
If plotFile belongs to your header file by declaring it via AnsiString plotFile; each translation unit gets its own copy. You need to define your variable in one *.cpp file and declare it as extern in your header.
From the C++ Standard:
3.5 Program and linkage
When a name has external linkage , the entity it denotes can be
referred to by names from scopes of other translation units or from
other scopes of the same translation unit.
So in your header file you have to place this:
extern AnsiString plotFile;
Define your variable in one cpp file:
AnsiString plotFile;
Don't use global variables for this, sooner or later you will get into trouble if you will always use this. One problem it causes is that you can use only once instance of your form because it is occupying your global variable.
There is a common solution to your problem that is I suppose identical on all platforms/systems/etc.. You have to pass your variable somehow to the form/dialog/etc class instance you want to show.
It looks like you are using Borland Builder C++, or Embarcadero. Proper way to solve your problem is to add AnsiString plotFile as a member variable of SelectElement form, and set it using accessor methods. Example code for it can be found here:
http://bcbjournal.org/articles/vol2/9810/Sharing_data_and_methods_between_forms.htm
I am a newbie in programming and apologise in advance if my question is too silly.
My c++ project is compiled as library .xll (DLL for excel), the framework code (program entry point) is coded correct and work stable. Custom functions are separate modules.
// header.h
typedef struct _TMDYDate {
long month;
long day;
long year;
} TMonthDayYear;
the file funcs.c has a function:
// funcs.c
#include "header.h"
__declspec(dllexport) long GetDate() {
TMonthDayYear myDate;
myDate.day = 1 ;
myDate.month = 1;
myDate.year = 2000;
if (DateToMDY(2004, &myDate) != 1) {
return 0;
}
return myDate.year;
}
where the function DateToMDY is declared in separate file Dates.c:
// dates.c
int DateToMDY (long tmpyear, TMonthDayYear *mdy) {
mdy->year = tmpyear; // <- Error is here
return 1;
}
I debug a function GetDate() and get an error when try to assign by reference (mdy->year = tmpyear;) the value 2004.
The error is:
Unhandled exception at 0x0e342b84 (alcDates.xll) in EXCEL.EXE: 0xC0000005: Access violation writing location 0x40e3db28
The funny thing is when i move declaration of DateToMDY to the file funcs.c, the same where the DateToMDY is called - there is no error.
I assume it is to wrong memory usage, but for me is critical to isolate functionality in different modules (ex. dates.c, array.c, sorting.c ...).
I don't know where to look for, may be i have wrong project compilation settings.
It seems like you call the function from a place where its declaration isn't visible. If you do, the compile does not know what types the parameters should have so it passes them all as ints.
Functions called from another .c file should be declared in the corresponding .h file,and included in all .c files using the function.
I am having difficulty in printing to a text file from chosen locations within a large C++ code project.
Using C++ I am using a function X which is called multiple times.
This is called from a function Y
I wish to output the results of function X to a single text file and have done so by continously using declarations, fopen, fprintf, fclose set of functions - this works – albeit very slowly.
However, I only wish to print results to file when X is called from a specific area of the host function Y.
I am looking to do so, whilist being minimally invasive with the current code (i.e. I wouldn’t like to add another argument to the function X, nor would I like to declare global variables).
Is their a way a unique methods to effectively ‘tell’ the code and child functions when to start printing to file and when to stop.
(p.s. I have post-processed my results using VBA however this workaround is found to be inefficient).
Any ideas or code constructs would be most welcome!
swarm
Below is the child function X:
void `X`() {
FILE *f2 = NULL;
f2 = fopen("log.txt", "a");
// Calculate a result: `result`
fprintf(f2, "%.4e ", result);
fclose (f2);
}
Below is the main calling function Y:
void Y Y(){
for i=1:100{
X();
X();
X(); // <-- Wishing to print only this line to a text file
}
}
Since you're in C++, you can add an overload of X that takes an argument of when to do it, and not have to change any callers.
You have
void X(args);
Add
void X(args, bool doIt);
Then, move the code in the original X to the new one, checking doIt.
In the original X, call X(args, false)
Somehow the boolean state of whether to actually log has to be passed. Choices are: an argument, a global, an member variable (static or instance), a thread local variable, or a file.
Whatever you do. it will probably be logically equivalent to declaring a global variable. But you can ease the pain of this in various ways:
If X is a class member, you can declare the variable as a static member of X's class.
If X belongs to a namespace, your global variable can belong to that namespace.
You can declare it as a static variable, local to X's source file, and use a function in the source file to set its value.
And so on.
If you don't want to keep binary compliance, than you can also transform X function to structure/class with overloaded operator() - then add field or method specyfying if you should print it or not. - however this is quite similar to another global variable. Except overloading X, i doubt there is any other method that doesn't use globals or something similar.
How are you keeping your FILE* pointer between X calls? global? stativ variable in function?