I have MCU with flash memory breaked in sections(as usual).
Linker places .struct_init, .struct_init_const, .struct_not_init sections to addresses belongs to flash memory section20. It is hardcoded in linker script.
Consider following test code:
test.h
typedef struct
{
int val1;
int val2;
} mystruct_t;
test.cpp
#include "test.h"
// each variable is placed in dedicated section
// sections are placed in flash section20
// linker exports symbols with address of eaach section
__attribute__((section(".struct_init")))
mystruct_t struct_init = {
.val1 = 1,.val2 = 2};
__attribute__((section(".struct_init_const")))
extern const mystruct_t struct_init_const = {
.val1 = 1, .val2 = 2};
__attribute__((section(".struct_not_init")))
mystruct_t struct_not_init;
main.cpp
#include <stdint.h>
// This symbols exported by linker
// contains addresses of corresponding sections
extern uintptr_t LNK_STRUCT_INIT_ADDR;
extern uintptr_t LNK_STRUCT_INIT_CONST_ADDR;
extern uintptr_t LNK_STRUCT_NOT_INIT_ADDR;
// Pointers for indirect access to data
mystruct_t* struct_init_ptr = (mystruct_t*)LNK_STRUCT_INIT_ADDR;
const mystruct_t* struct_init_const_ptr = (const mystruct_t*)LNK_STRUCT_INIT_CONST_ADDR;
mystruct_t* struct_not_init_ptr = (mystruct_t*)LNK_STRUCT_NOT_INIT_ADDR;
// Extern variables declarations for DIRECT access data
extern mystruct_t struct_init;
extern const mystruct_t struct_init_const;
extern mystruct_t struct_not_init;
// This is some variables representing config values
// They can be more complex objects(classes) with internal state and logic..
int param1_direct;
int param1_init_const_direct;
int param1_not_init_direct;
int param1_indirect;
int param2_init_const_indirect;
int param1_not_init_indirect;
int main(void)
{
// local variables init with direct access
int param1_direct_local = struct_init.val1;
int param1_init_const_direct_local = struct_init_const.val1;
int param1_not_init_direct_local = struct_not_init.val1;
// local variables init with indirect access
int param1_indirect_local = struct_init_ptr->val1;
int param2_init_const_indirect_local = struct_init_const_ptr->val1;
int param1_not_init_indirect_local = struct_not_init_ptr->val1;
//global variables init direct
param1_direct = struct_init.val1;
param1_init_const_direct = struct_init_const.val1;
param1_not_init_direct = struct_not_init.val1;
//global variables init indirect
param1_indirect = struct_init_ptr->val1;
param2_init_const_indirect = struct_init_const_ptr->val1;
param1_not_init_indirect = struct_not_init_ptr->val1;
while(1){
// use all variables we init above
// usage of variables may also occure in some functions or methods
// directly or indirectly called from this loop
}
}
I wanna be sure that initialization of param1_ variables will lead to fetch data from flash. Because data in flash section20 can be changed using bootloader(at the moment when main firmware is not running).
The question is: Can LTO(and other optimizations) throw away fetches from flash and just substitute known values because they are known at link time because of initialization.
What approach is better?
If LTO can substitute values - then initialization should be avoided?
I know volatile can help, but is it really needed in this situation?
Code exampe shows different approaches of accessing and initializing data.
not_init version seems to be the best, because compiler can't substitute anything. But it will be a good idea to have some default parameters, so i'd prefer init version if it can be used.
What approach should be chosen?
Currently i am using GCC 4.9.3 but this is general question about any C/C++ compiler.
C and C++ both feature extern variables, which lets you define constants without immediately giving away their values:
// .h
extern int const param1;
extern char const* const param2;
// ...
In general you would define them in a (single) source file, which would hide them away from anything not in this source file. This is not LTO resilient, of course, but if you can disable LTO it is an easy enough strategy.
If disabling LTO is not an option, another solution is to not define them, let LTO produce a binary, and then use a script to splice the definitions in the produced binary in the right section (the one that can be flashed).
With the value not available at LTO time, you are guaranteed that it will not be substituted.
As for the solutions you presented, while volatile is indeed a standard compliant solution, it implies that the value is not constant, which prevents caching it during run-time. Whether this is acceptable or not is for you to know, just be aware it might have a performance impact, which as you are using LTO I surmised you would like to avoid.
Related
I have a C program which I need to connect to a C++ API. I asked on here and was given great advice, leading to creating a "wrapper".
So, in the API there is a type called "APIName::ReturnCode", and I wanted to create a C equivalent, so I've done the following:
In c_api.h:
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void* API_ReturnCode_t;
EXTERNC API_ReturnCode_t api_returncode_init();
EXTERNC void api_returncode_destroy(API_ReturnCode_t rc);
#undef EXTERNC
in c_api.cpp:
#include "c_api.h"
#include "/path/to/api/api.h"
API_ReturnCode_t api_returncode_init() {
return new APIName::ReturnCode;
}
void api_returncode_destroy(API_ReturnCode_t untyped_ptr) {
APIName::ReturnCode* typed_ptr = static_cast< APIName::ReturnCode*>(untyped_ptr);
delete typed_ptr;
}
So I compile that into a library and include it in my main program, and I can use things like:
API_ReturnCode rc;
to define a variable.
However, my next issue is how to define enumerated types in a similar way. So, the api has the following definition for error codes:
namespace APIName {
typedef enum ReturnCode_enum ReturnCode;
enum ReturnCode_enum {
RC_OK , // success
RC_ERROR , // general error
RC_NOT_AVAILABLE , // feature is not available
};
}
How do I recreate this in my wrapper so that I can do something like this in my code:
API_ReturnCode rc = API_RC_OK;
Thank you.
So after some clarification, my original answer is no longer applicable -- but is still retained below this answer.
Since the original C++ API cannot be altered in any way, you are much more limited in your available options.
You want to be able to do:
API_ReturnCode rc = API_RC_OK;
But rc is an opaque type (void*) that requires being destroyed with api_returncode_destroy -- so this won't be possible in an easy and sane way (not without confusing who owns the API_RC_OK calls). The biggest issue is that if we could produce an API_RC_OK instance, it leads to questionable ownership. For example:
API_ReturnCode rc = API_RC_OK;
api_returncode_destroy(rc); // is this good? is 'API_RC_OK' a resource that needs deleting?
And it gets more confusing in more complicated expressions.
Since the APIName::ReturnCode_enum type is just a classic C-style enum, which is implicitly convertible to an int, your best-bet here would be to try to preserve the int-like property by making API_ReturnCode_t's definition be:
typedef int API_ReturnCode_t;
Then any of the C++-wrapped calls can propagate the values as this int
Unfortunately to be able to receive these values on the other side, you will need to duplicate some effort here by manually re-creating these constants in some way. There are a few approaches that come to mind, all with pros and cons.
The inconvenient truth here is that, because you're trying to expose values defined in C++ in C, you'll need to somehow re-encode this on the other side in some way. You can't simply include the C++ header and use it in C, since they are different languages and C++ contains features that C doesn't understand.
1. Use extern constants
One possible approach is to use extern const values that get defined in the source from the underlying values, so you aren't stuck duplicating the values themselves. For example:
c_api.h
EXTERNC extern const API_ReturnCode_t API_RC_OK;
EXTERNC extern const API_ReturnCode_t API_RC_ERROR;
EXTERNC extern const API_ReturnCode_t API_RC_NOT_AVAILABLE;
c_api.cpp
extern "C" {
const API_ReturnCode_t API_RC_OK = APIName::RC_OK;
const API_ReturnCode_t API_RC_ERROR = APIName::RC_ERROR;
const API_ReturnCode_t API_RC_NOT_AVAILABLE = APIName::RC_NOT_AVAILABLE;
} // extern "C"
The good thing with this approach is that you aren't stuck manually setting API_RC_OK to 0, and API_RC_ERROR to 1, etc -- so these values are not strongly coupled.
The thing to watch out for is that these extern constants would not be (safely) usable from other objects during static initialization, since it's not guaranteed when these values will be set. If you aren't doing much static initialization, this shouldn't be of any concern.
2. Just duplicate the effort
If the enum is not large, and not likely to grow much larger, the obvious simple approach is to just do:
#define API_RC_OK 0
#define API_RC_ERROR 1
#define API_RC_NOT_AVAILABLE 2
or some equivalent thereof. The pro is that this can be used anywhere, compared to extern constants. The obvious con here is that the wrapper is strongly coupled to the wrapped library. If this is a large enumeration, or an enum that is likely to change often / regularly -- this is approach is probably not the best.
3. Define a possibly-orthogonal enumeration
One other option is to define an orthogonal enumeration instead. This requires re-defining the enum cases that you care about, and translating them through a separate function call. This results in more effort -- so depending on what you're doing, this may not be the best case.
c_api.h
typedef enum {
API_RC_OK,
API_RC_ERROR,
API_RC_NOT_AVAILABLE,
/* other states? */
} API_ReturnCode_t;
**c_api.cpp
API_ReturnCode_t to_return_code(APIName::ReturnCode rc)
{
switch (rc) {
case APIName::RC_OK: return API_RC_OK;
case APIName::RC_ERROR: return API_RC_ERROR;
case APIName::RC_NOT_AVAILABLE: return API_RC_NOT_AVAILABLE;
}
return API_RC_NOT_AVAILABLE;
}
In your wrapper code, anywhere you receive an APIName::ReturnCode you would now translate to an API_ReturnCode_t before returning back to the C caller.
The nice thing about this approach is that the enumerators no longer need to be in-sync, and that you can restrict the enum cases that you want to abstract out (assuming you don't want 1-1 mapping).
This also presents an easier way to upgrade in the future to different versions of the C++ library, since everything is internalized by the translation function. If the C++ library introduces new states, you can choose to coalesce some of those values together in a way that may make it more consumable by the C client.
The obvious downside with this approach is that it takes more work, since you're defining a separate hierarchy and a translation system that will be quite similar in the beginning. It's more work up-front for a higher return later on.
Old Answer
There is nothing specific to C++ about your ReturnCode_enum class. It's actually written in a more legacy-C++ style (e.g. not using enum class for scoping), which makes it usable in C directly.
So why not define the enum in the c_api.h header file instead, and use it in your C++ as well? This may require changing your opaque handle definition depending on what is stored in it; but this way you would have exactly 1 definition of the enumeration.
You can bring the C symbol into C++ namespaces using either typedef or using aliases, which allow a more C++-esque discovery of the values.
In c_api.h:
enum Api_ReturnCode_enum {
RC_OK , /* success */
RC_ERROR , /* general error */
RC_NOT_AVAILABLE , /* feature is not available */
};
/*
or 'typedef enum { ... } Api_ReturnCode_enum;' if you want don't want to specify
'enum' every time in C
*/
In your C++ API:
#include "c_api.h"
namespace APIName { // bring it into this namespace:
// Alias the "Api_" prefixed enum to be more C++ like
typedef Api_ReturnCode_enum ReturnCode;
// alternative, in C++11 or above:
// using ReturnCode = Api_ReturnCode_enum;
}
I wouldn't hide error code enums in opaque handles.
Create a new enum and convertion functions in the c_api.cpp file
c_api.h
typedef enum {
RC_OK,
RC_ERROR,
RC_NOT_AVAILABLE
} ReturnCode_copy;
ReturnCode_copy some_function(...);
c_api.cpp
static ReturnCode_copy convert(APIName::ReturnCode code) {
switch(code) {
//return correct ReturnCode_copy
}
}
ReturnCode_copy some_function(...) {
auto code = //some api function returning error code
return convert(code);
}
or you could be naughty and just copy the values directly in your new enum and just static_cast directly without the convert function.
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’m trying to JIT compile some functions in an existing C/C++ program at runtime, but I’m running into some trouble with global variable initialization. Specifically, the approach I’ve taken is to use Clang to precompile the program into IR bitcode modules in addition to the executable. At runtime, the program loads the modules, transforms them (program specialization), compiles and executes them. As it turns out, I have some global variables that get initialized and modified during execution of the “host” program. Currently, these globals are also getting initialized in the JIT compiled code, whereas I’d like them to be mapped to the host global variables instead. Can someone help me with this?
A small repro is excerpted below. Full source code is here. The file somefunc.cpp gets precompiled during build, and is loaded in the main() function in testCompile.cpp. The global variable xyz is initialized to point to 25 in somefunc.cpp, but I’d like it to point to 10 as in main() instead. In other words, the assertion in main() should succeed.
I tried a few different ways to solve this problem. The ChangeGlobal() function attempts (unsuccessfully) to achieve this updateGlobalMapping(). The second, more hacky approach uses a new global variable initialized appropriately. I can get this latter approach to work for some types of globals, but is there a more elegant approach than this?
//————— somefunc.h ————————
extern int *xyz;
//—————— somefunc.cpp ——————
int abc = 25;
int *xyz = &abc;
int somefunc() {
return *xyz;
}
//—————— testCompile.cpp ——————
class JitCompiler {
public:
JitCompiler(const std::string module_file);
void LoadModule(const std::string& file);
template <typename FnType>
FnType CompileFunc(FnType fn, const std::string& fn_name);
void ChangeGlobal();
private:
std::unique_ptr<LLVMContext> context_;
Module *module_;
std::unique_ptr<ExecutionEngine> engine_;
};
void JitCompiler::ChangeGlobal() {
// ----------------- #1: UpdateGlobalMapping -----------------
//auto g = engine_->FindGlobalVariableNamed("xyz");
//engine_->updateGlobalMapping(g, &xyz);
//assert(engine_->getGlobalValueAddress("xyz") == (uint64_t) &xyz);
// ----------------- #2: Replace with new global ————————
// ------- Ugly hack that works for globals of type T** ----------
auto g = engine_->FindGlobalVariableNamed("xyz");
Constant *addr_i = ConstantInt::get(*context_, APInt(64, (uint64_t) xyz));
auto addr = ConstantExpr::getIntToPtr(
addr_i, g->getType()->getPointerElementType());
GlobalVariable *n = new GlobalVariable(
*module_,
g->getType()->getPointerElementType(),
g->isConstant(),
g->getLinkage(),
addr,
g->getName() + "_new");
g->replaceAllUsesWith(n);
n->takeName(g);
g->eraseFromParent();
}
int main() {
xyz = new int (10);
JitCompiler jit("somefunc.bc");
jit.ChangeGlobal();
auto fn = jit.CompileFunc(&somefunc, "somefunc");
assert(somefunc() == fn());
}
A better approach is the combination of the two you presented, that is, to create a new global with external linkage mapped to &xyz and substitute it for the original:
auto g = engine_->FindGlobalVariableNamed("xyz");
GlobalVariable *n = new GlobalVariable(
g->getType()->getPointerElementType(),
g->isConstant(),
ExternalLinkage
nullptr,
g->getName() + "_new");
engine_->updateGlobalMapping(n, &xyz);
g->replaceAllUsesWith(n);
n->takeName(g);
g->eraseFromParent();
Learning C++ with help of "Thinking in C++" by Bruce Eckel,stuck in exercise 32, chapter 10.
The question is how to change link order, that Mirror::test() called for object m5 return false.
Here is my code.
mirror.h:
#ifndef MIRROR_H_
#define MIRROR_H_
class Mirror {
public:
Mirror() {logic_ = true; self_ = 0;};
Mirror(Mirror *ptr) {self_ = ptr; logic_ = false;};
bool test() {
if (self_ != 0) {
return self_->test();
} else {
return logic_;
}
};
private:
bool logic_;
Mirror *self_;
};
#endif // MIRROR_H_
task
one.cpp
#include "mirror.h"
Mirror m1;
two.cpp
#include "mirror.h"
extern Mirror m1;
Mirror m2 (&m1);
three.cpp
#include "mirror.h"
extern Mirror m2;
Mirror m3 (&m2);
and so on. Finally,
five.cpp
#include "mirror.h"
#include <iostream>
extern Mirror m4;
Mirror m5 (&m4);
int main(int argc, char* argv[]) {
std::cout << m5.test() << std::endl;
}
m5.test() returns true. The task says, that I should change linking order, that m5.test() returns false. I have tried to use:
init_priority (priority)
In Standard C++, objects defined at namespace scope are guaranteed to be initialized in an order in strict accordance with that of their
definitions in a given translation unit. No guarantee is made for
initializations across translation units. However, GNU C++ allows
users to control the order of initialization of objects defined at
namespace scope with the init_priority attribute by specifying a
relative priority, a constant integral expression currently bounded
between 101 and 65535 inclusive. Lower numbers indicate a higher
priority.
but no luck.
Full exercise text:
In a header file, create a class Mirror that contains two data
members: a pointer to a Mirror object and a bool. Give it two
constructors: the default constructor initializes the bool to true and
the Mirror pointer to zero. The second constructor takes as an
argument a pointer to a Mirror object, which it assigns to the
object’s internal pointer; it sets the bool to false. Add a member
function test( ): if the object’s pointer is nonzero, it returns the
value of test( ) called through the pointer. If the pointer is zero,
it returns the bool. Now create five cpp files, each of which includes
the Mirror header. The first cpp file defines a global Mirror object
using the default constructor. The second file declares the object in
the first file as extern, and defines a global Mirror object using the
second constructor, with a pointer to the first object. Keep doing
this until you reach the last file, which will also contain a global
object definition. In that file, main( ) should call the test( )
function and report the result. If the result is true, find out how to
change the linking order for your linker and change it until the
result is false.
You'll need to change the order of the object files when passing them to the linker. This works reasonable for the toplevel code although different compilers use different approaches, i.e., it isn't portable. Also, for libraries you generally can't control the order in which the objects are included. For example, if you have
// file1.cpp
int main() {
}
// file2.cpp
#include <iostream>
static bool value = std::cout << "file2.cpp\n";
// file3.cpp
#include <iostream>
static bool value = std::cout << "file3.cpp\n";
... and you link two programs like this:
g++ -o tst1 file1.cpp file2.cpp file3.cpp
g++ -o tst2 file1.cpp file3.cpp file2.cpp
you will get different output for tst1 and tst2, e.g.:
$ ./tst1
file2.cpp
file3.cpp
$ ./tst2
file3.cpp
file2.cpp
The overall moral is: don't do it. That is: don't use global objects. If you feel you absolutely need to use global objects, encapsulate them into functions, e.g.:
Type& global_value() {
static Type value; // possibly with constructor arguments
return value;
}
This way, value is initialized the first time it is accessed and there is no way to access it while it isn't constructed, yet. If you encapsulate all objects like this, you can guarantee that they are constructed in an appropriate order (unless you have a cyclic dependency in which case it can't be made to work and you should seriously rethink your design). The above approach encapsulating objects into function is, unfortunately, not thread-safe in C++ 2003. It is thread-safe in C++ 2011, however. Still, use of global variable is generally problematic and you definitely want to minimize their use.
I was struggling with this exercise too.
I managed to write a small Python script to prepare makefile entries that link and test final executable using all possible permutation of object files:
import itertools
for perm in itertools.permutations([1, 2, 3, 4, 5]):
print '\tg++ u0{0}.o u0{1}.o u0{2}.o u0{3}.o u0{4}.o -o $# && ./main.exe'.format(*perm)
After executing my make process it turned out, that all of the possible configurations yielded true value.
This is due to the fact, that all global (i.e. static) variables are guaranteed to be initialized before entering main function.
I defined a global bool variable that holds result from a test() function before main, something like this:
#include "mirror.h"
#include <iostream>
extern Mirror m4;
Mirror m5 (&m4);
bool result = m5.test();
int main(int argc, char* argv[]) {
std::cout << result << std::endl;
}
Bingo! Some of the objects' permutations yielded false at the progam's output.
All static variables are initialized with zeroes before any of their possible constructors are called. In this exercise, the order in which constructors are called is the clue.
If any object in the depencence chain has not been initialized by constructor when a value of result variable is established, the result is false value (self_ value is 0 and logic_ value is false, so test function returns false).
When a result variable is evaluated before entering main function, there is such possibility and order of object files in a linker command has something to do with the result.
I'm trying to initialize a global array of function pointers at compile-time, in either C or C++. Something like this:
module.h
typedef int16_t (*myfunc_t)(void);
extern myfunc_array[];
module.cpp
#include "module.h"
int16_t myfunc_1();
int16_t myfunc_2();
...
int16_t myfunc_N();
// the ordering of functions is not that important
myfunc_array[] = { myfunc_1, myfunc_2, ... , myfunc_N };
func1.cpp, func2.cpp, ... funcN.cpp (symbolic links to a single func.cpp file, so that different object files are created: func1.o, func2.o, func3.o, ... , funcN.o. NUMBER is defined using g++ -DNUMBER=N)
#include "module.h"
#define CONCAT2(x, y) x ## y
#define CONCAT(x, y) CONCAT2(x, y)
int16_t CONCAT(myfunc_, NUMBER)() { ... }
When compiled using g++ -DNUMBER=N, after preprocessing becomes:
func1.cpp
...
int16_t myfunc_1() { ... }
func2.cpp
...
int16_t myfunc_2() { ... }
and so on.
The declarations of myfunc_N() and the initialization of myfunc_array[] are not cool, since N changes often and could be between 10 to 200. I prefer not to use a script or Makefile to generate them either. The ordering of functions is not that important, i can work around that. Is there a neater/smarter way to do this?
How To Make a Low-Level Function Registry
First you create a macro to place pointers to your functions in a special section:
/* original typedef from question: */
typedef int16_t (*myfunc)(void);
#define myfunc_register(N) \
static myfunc registered_##myfunc_##N \
__attribute__((__section__(".myfunc_registry"))) = myfunc_##N
The static variable name is arbitrary (it will never be used) but it's nice to choose an expressive name. You use it by placing the registration just below your function:
myfunc_register(NUMBER);
Now when you compile your file (each time) it will have a pointer to your function in the section .myfunc_registry. This will all compile as-is but it won't do you any good without a linker script. Thanks to caf for pointing out the relatively new INSERT AFTER feature:
SECTIONS
{
.rel.rodata.myfunc_registry : {
PROVIDE(myfunc_registry_start = .);
*(.myfunc_registry)
PROVIDE(myfunc_registry_end = .);
}
}
INSERT AFTER .text;
The hardest part of this scheme is creating the entire linker script: You need to embed that snippet in the actual linker script for your host which is probably only available by building binutils by hand and examining the compile tree or via strings ld. It's a shame because I quite like linker script tricks.
Link with gcc -Wl,-Tlinkerscript.ld ... The -T option will enhance (rather than replace) the existing linker script.
Now the linker will gather all of your pointers with the section attribute together and helpfully provide a symbol pointing before and after your list:
extern myfunc myfunc_registry_start[], myfunc_registry_end[];
Now you can access your array:
/* this cannot be static because it is not know at compile time */
size_t myfunc_registry_size = (myfunc_registry_end - myfunc_registry_start);
int i;
for (i = 0; i < myfunc_registry_size); ++i)
(*myfunc_registry_start[i])();
They will not be in any particular order. You could number them by putting them in __section__(".myfunc_registry." #N) and then in the linker gathering *(.myfunc_registry.*), but the sorting would be lexographic instead of numeric.
I have tested this out with gcc 4.3.0 (although the gcc parts have been available for a long time) and ld 2.18.50 (you need a fairly recent ld for the INSERT AFTER magic).
This is very similar to the way the compiler and linker conspire to execute your global ctors, so it would be a whole lot easier to use a static C++ class constructor to register your functions and vastly more portable.
You can find examples of this in the Linux kernel, for example __initcall is very similar to this.
I was going to suggest this question is more about C, but on second thoughts, what you want is a global container of function pointers, and to register available functions into it. I believe this is called a Singleton (shudder).
You could make myfunc_array a vector, or wrap up a C equivalent, and provide a function to push myfuncs into it. Now finally, you can create a class (again you can do this in C), that takes a myfunc and pushes it into the global array. This will all occur immediately prior to main being called. Here are some code snippets to get you thinking:
// a header
extern vector<myfunc> myfunc_array;
struct _register_myfunc {
_register_myfunc(myfunc lolz0rs) {
myfunc_array.push_back(lolz0rs);
}
}
#define register_myfunc(lolz0rs) static _register_myfunc _unique_name(lolz0rs);
// a source
vector<myfunc> myfunc_array;
// another source
int16_t myfunc_1() { ... }
register_myfunc(myfunc_1);
// another source
int16_t myfunc_2() { ... }
register_myfunc(myfunc_2);
Keep in mind the following:
You can control the order the functions are registered by manipulating your link step.
The initialization of your translation unit-scoped variables occurs before main is called, i.e. the registering will be completed.
You can generate unique names using some macro magic and __COUNTER__. There may be other sneaky ways that I don't know about. See these useful questions:
Unnamed parameters in C
Unexpected predefined macro behaviour when pasting tokens
How to generate random variable names in C++ using macros?
Your solution sounds much too complicated and error prone to me.
You go over your project with a script (or probably make) to place the -D options to the compiler, anyhow. So I suppose you are keeping a list of all your functions (resp. the files defining them).
I'd use proper names for all the functions, nothing of your numbering scheme and then I would produce the file "module.cpp" with that script and initialize the table with the names.
For this you just have to keep a list of all your functions (and perhaps filenames) in one place. This could be easier be kept consistent than your actual scheme, I think.
Edit: Thinking of it even this might also be overengineering. If you have to maintain a list of your functions somewhere in any case, why not just inside the file "module.cpp"? Just include all the header files of all your functions, there, and list them in the initializer of the table.
Since you allow C++, the answer is obviously yes, with templates:
template<int N> int16_t myfunc() { /* N is a const int here */ }
myfunc_array[] = { myfunc<0>, myfunc<1>, myfunc<2> }
Now, you might wonder if you can create that variable-length initializer list with some macro. The answer is yes, but the macro's needed are ugly. So I'n not going to write them here, but point you to Boost::Preprocessor
However, do you really need such an array? Do you really need the name myfunc_array[0] for myfunc<0> ? Even if you need a runtime argument (myfunc_array[i]) there are other tricks:
inline template <int Nmax> int16_t myfunc_wrapper(int i) {
assert (i<Nmax);
return (i==Nmax) ? myfunc<Nmax> : myfunc_wrapper(i-1);
}
inline int16_t myfunc_wrapper(int i) {
return myfunc_wrapper<NUMBER>(i); // NUMBER is defined on with g++ -DNUMBER=N
}
Ok I worked out a solution based on Matt Joiner's tip:
module.h
typedef int16_t (*myfunc_t)(void);
extern myfunc_array[];
class FunctionRegistrar {
public:
FunctionRegistrar(myfunc_t fn, int fn_number) {
myfunc_array[fn_number - 1] = fn; // ensures correct ordering of functions (not that important though)
}
}
module.cpp
#include "module.h"
myfunc_array[100]; // The size needs to be #defined by the compiler, probably
func1.cpp, func2.cpp, ... funcN.cpp
#include "module.h"
static int16_t myfunc(void) { ... }
static FunctionRegistrar functionRegistrar(myfunc, NUMBER);
Thanks everyone!