invalid conversion from 'long int' to 'void (*)()' [-fpermissive] - c++

Hi I am writing little modified code for the bootloader for MCU's. The modification I am trying to do is power the boot loader even for an watchdog timer reset.
I am using this function prototype to define the address of the boot loader and I get the error :
invalid conversion from 'long int' to 'void (*)()' [-fpermissive]
My code is
#if defined ( __AVR_ATmega1284P__ )
void (*boot_start)(void) = 0xF000;
#elif defined ( __AVR_ATmega2560__ )
void (*boot_start)(void) = 0x1F000;
#endif
Where the 0xF000 and 0x1F000 are memory spaces. I don't get this error if my code is `
void (*boot_start)(void) = 0x0000;
Why ??

Compiler recognize 0xF000 as int and discard assigning this value to pointer. You should cast it explicitly:
void (*boot_start)(void) = (void (*)())0xF000;

0x0000 is just another name for NULL and will compile ok as a pointer value, but the other values need to be explicitly cast to the correct type.

The answer that I got from AVRFreak forum,
USE TYPEDEF,
typedef void (*fptr_t)(void);
fptr_t boot_start = (fptr_t)0xF000;
...
boot_start();
The reason you get the warning otherwise is that 0xF000 is a long int for an AVR. The thing on the left of '=' was a pointer to a function. So you are trying to assign an integer to a pointer. C thinks this is probably a mistake (often it is!) so it warns you. The way you quell that warning is to say "no this 0xF000 number really is a pointer value". The way you do that is with a typecast. Now you could do this with (wait for it):
void (*boot_start)(void) = (void(*)(void))0xF000;
But as you can see in that there is almost exactly the same (quite complex) structure on both side of the equals. So it makes sense to put all that detail into one single typedef and use it in multiple places.
If the function type were more complex this might even be something like:
int (*boot_start)(char, long, int *) = (int (*)(char, long, int *))0xF000;
and this starts to look very silly indeed - not only is it very likely you make a typing error it's just trying to remember the syntax here is a real pain! So you use typedef to define the function interface just once:
typedef int (*myfn_t)(char, long, int *);
myfn_t boot_start = (myfn_t))0xF000;
and that gets to be easier to type and easier to manage. If you later add a fourth char ** parameter to the function you now do it in just one place - the typedef.
Thanks to C Lawson and Yuriy.

Related

C++ Cast from ‘std::__tuple... {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision

You may have to forgive me as I'm new to C++ and may have made some fundamental errors with the code I have worked up so far.
static tuple<read_result, uint8_t*> m_scan_record(bool skip, uint32_t& size, FILE* file)
{
read_result result;
tuple<read_result, uint32_t*> rd_rec_size_result = m_read_generic_t<uint32_t>(file);
result = (read_result)get<0>(rd_rec_size_result);
if (result != read_success )
{
return tuple<read_result, uint8_t*>(result, nullptr);
}
size = (uint32_t) get<1>(rd_rec_size_result);
if ( skip )
{
fseek(file, size, SEEK_CUR);
}
// ...
}
template<typename T>
static tuple<read_result, T*> m_read_generic_t(FILE* file)
{
T ret = 0;
read_result result = m_read_from_file_to_buffer(&ret, sizeof(T), file);
if (result == read_success)
{
return tuple<read_result, T*>(result, &ret);
}
return tuple<read_result, T*>(result, nullptr);
}
When I compile this code I am getting this error:
cast from ‘std::__tuple_element_t<1, std::tuple<read_result, unsigned int*> >’ {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
My intentions and what I am expected to do/happen:
In the declaration of m_scan_record, the size argument is declared with a & which is intended to allow me to pass the value by reference, analogous to using the REF c# keyword
I make a call to generic (template) function m_read_generic_t which is called with the specified type <unit32_t> and therefore (according to its definition) will return a type of tuple<read_result, uint32_t*>
Once I have the tuple returned by m_read_generic_t, I want to take the unit32_t value pointed to by the second value of the tuple, and put that value into the size variable mentioned at point 1, above, which presumably will then be accessible to the calling function one step further up the stack.
From the above points you can hopefully see that my intention (and I appreciate that I may be far away in reality!) is that at this line:
size = (uint32_t) get<1>(rd_rec_size_result);
all I am doing is simply grabbing a 'pointed to' value and putting it into a variable of a matching type, much like the oft-cited textbook example:
uint32_t v = 123;
uint32_t* ptr_to_v = &v;
uint32_t x = ptr_to_v; // x == 123
Clearly this is not what is really going on with my code, though, because if it were, I presume that the cast would be un-needed. But if I remove it, like this:
size = get<1>(rd_rec_size_result);
then I get a compile-time error:
a value of type "std::__tuple_element_t<1UL, std::tuple<read_result, uint32_t *>>" cannot be assigned to an entity of type "uint32_t"
I believe therefore that I am doing something badly wrong - but I can't work out what. Is this to do with the way I am taking the pointer out of the tuple; or is there something else going on when it comes to the getting a uint32_t value from a uint32_t* ?
This is all in a C++ environment on Ubuntu 20.04, FWIW
Many thanks in advance for any/all suggestions; please go easy on me!
tuple<read_result, uint32_t*> rd_rec_size_result = ...
The 2nd member of this tuple, as explicitly declared here, is a pointer to a uint32_t. That's what uint32_t * means, in C++.
size = (uint32_t) get<1>(rd_rec_size_result);
This retrieves the uint32_t * and attempts to convert it to a uint32_t. C++ does not work this way. Although this conversion can be forced your compiler has every right to believe that whatever this code is trying to do it must be wrong.
Perhaps I was wondering initially, your intention was to dereference the pointer. This is the reason for your compilation error, in any case. If your intention was to, truly, dereference this pointer, then this would've been a simple matter of changing this to
size = *get<1>(rd_rec_size_result);
However, that's not going to be the end of your troubles. Even after this compilation error is fixed, this way, the shown code will still be badly, badly broken.
This is because m_read_generic_t returns a pointer to a local object, which will get destroyed when the function returns, and attempting to dereference this pointer, here, will make demons fly out of your nose.
The real fix here is to change m_read_generic_t to not return a pointer as the 2nd value in the tuple in the first place, thus eliminating the compilation error in the first place.

Trying to get past std::bind compile errors

I've used std::bind before and I think am close on this usage but not quite there and I don't have a clue how to resolve the compile error.
The ultimate goal is a medium-sized array of pointers to a small number of functions, with different parameters in each array element. At this point I just have one function and one table entry. If I can get that right I think I can solve the rest. I want to use std::function so that I can put the varied parameters into the array.
Here's declaration of the one function so far:
static Get *MakeGArrayStatic(void *Subscript, const void **array, unsigned int sizeOfArray);
Here's the declaration of the single pointer that will be typical of the array:
typedef std::tr1::function<Get *(void *, const void**, unsigned int)> GetMaker;
static GetMaker *gm1;
Here's the definition of the pointer:
Get::GetMaker *Get::gm1 = std::tr1::bind(&MakeGArrayStatic, &OutMsg::CurrentSeverity, FacSevTbls::SyslogSeveritiesForMessages, FacSevTbls::NumberOfTrueSeverities);
(Get is a class, CurrentSeverity is an enum, SyslogSeveritiesForMessages is a const char **, and NumberOfTrueSeverities is a size_t.)
The error I am getting (VS 2010) is
error C2440: 'initializing' : cannot convert from 'std::tr1::_Bind<_Result_type,_Ret,_BindN>' to 'Get::GetMaker *'
with
[
_Result_type=Get *,
_Ret=Get *,
_BindN=std::tr1::_Bind3,SyslogEnums::SeverityEnum *,const char **,size_t>
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
Can anyone please point out where I am going wrong?
Thank you again to #PlinyTheElder but I think we have left the question "officially" unanswered. Closing the loop, here are the declarations with the first cut at an array of functions:
static Get *MakeGArrayStatic(void *Subscript, const char **array, size_t sizeOfArray);
static Get *MakeGStatic(void *field, size_t sizeOfField);
typedef std::tr1::function<Get *()> GetMaker;
static GetMaker gm[];
and here is the definition of the array so far:
std::tr1::function<Get *()> Get::gm[] = {
std::tr1::bind(&Get::MakeGArrayStatic, &OutMsg::CurrentSeverity, FacSevTbls::SyslogSeveritiesForMessages, FacSevTbls::NumberOfTrueSeverities),
std::tr1::bind(&MakeGStatic, Msg::MessageID, 8) } ;
And here is a trivial example of a call to a function:
Get *g = Get::gm[0]();
Came out better than I had hoped. I had pictured that all of the "little functions" were going to have to have the same signature (like overloads). Compiles cleanly on both target compilers. (Have not tested execution yet, but I am confident.) Thanks again!
Update: yes, it executes.

Understanding casting a struct as a void pointer

I found this code in the rendering library for Quake 3. There is this function:
void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int fogIndex, int dlightMap );`
It is being called in a loop somehwere else like this:
R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex, qfalse );
The weird part is that poly was declared as srfPoly_t *poly. What is going on
here? It is casting a srfPoly_t object to (void *) and then entering the
function as a surfaceType_t object.
Here are the declaration for the relevant structs:
typedef enum {
SF_BAD,
SF_SKIP, // ignore
SF_FACE,
SF_GRID,
SF_TRIANGLES,
SF_POLY,
SF_MD3,
SF_MD4,
SF_FLARE,
SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity
SF_DISPLAY_LIST,
SF_NUM_SURFACE_TYPES,
SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int )
} surfaceType_t;
typedef struct srfPoly_s {
surfaceType_t surfaceType;
qhandle_t hShader;
int fogIndex;
int numVerts;
polyVert_t *verts;
} srfPoly_t;
This is working in C, but I am trying to implement something similar in C++,
but I get the following error:
Error 1 error C2664: 'int RefDef::AddDrawSurf(surfaceType_t *)' : cannot convert argument 1 from 'void *' to 'surfaceType_t *'
It would appear I cannot perform this type of cast in C++, or maybe there is
something else I am unable to understand. I am not very familiar with C++ and
would love to figure out how to set up something similar using it.
I am assuming this has something to do with type checking in C++, so it is not
allowed. How can I implement something similar in C++ in a safe way?
This works in C because structs are simply blocks of memory with each element in the struct laid out consecutively. This cast works because the first n bytes of a srfPoly_t struct consist of the surfaceType_t enum within that struct. The called function tries to interpret the passed-in srfPoly_t as a surfaceType_t, and succeeds because the first n bytes of the argument are, in fact, a surfaceType_t. Do not do this without a very good reason.
Casts from void*'s do not automatically occur in C++ as they do in C. You can use reinterpret_cast to explicitly cast between two different types of structs:
srfPoly_t* mySrfPoly_t;
surfaceType_t* mySurfaceType = reinterpret_cast<surfaceType_t*>(mySrfPoly_t);

C++ Indexing an array of ints using a short

Ok guys I asked a question 15 mins ago and closed it because when I tried a simple test in main(), it worked. However, it does not work in the actual code:
Background, I have an array of unsigned ints which I cannot access via an unsigned short indexer. If I declare an array on the stack it works, but it doesnt work for my array data member.
Here is the array declaration:
typedef unsigned int uint;
class OB{
public:
OB();
void x(unsigned short side_pos);
private:
uint best_p[2];
};
and here's the code where I get the compiler error:
void OB::x(unsigned short side_pos){
unsigned int best_price = best_p[side_pos];
}
If I do:
void OB::x(unsigned short side_pos){
unsigned short something_else = 1;
unsigned int best_price = best_p[something_else];
}
I also get the compiler error, which is:
OB.cpp: In member function ‘void OB::x(short unsigned int)’:
OB.cpp:62:56: error: invalid types ‘unsigned int[short unsigned int]’ for array subscript
unsigned int best_price = best_p[side_pos];
It compiles on my computer. Seems the way to get that error is to use a variable instead of an array. Check the names of your attributes.
Based on intuition and comment hints, you have a local variable best_p (an unsigned int by the looks of it) that's shadowing the member of your class. Thus, best_p[side_pos] will use the local variable, not the data member.
If you want the compiler to catch shadowing, the -Wshadow option should do it. The best thing to do when it does is rename something. Having a convention for data member names (m_<name> is a common one) can also help to prevent both accidental shadowing and thinking about what to rename something to.

Detours - Hooking a Classes Member Function - Syntax for setting function offset of target?

For non class functions - I can simply declare the offset of the function to be detoured like:
typedef int (_cdecl* SomeFunc)(char* pBuffer, int size);
SomeFunc Real_SomeFunc = (SomeFunc)(0xCAFEBABE);
...
DetourAttach(&(PVOID&)Real_SomeFunc, (PVOID)Hook_SomeFunc);
Now, this gets hard with detouring member functions of classes - detours has a sample for this:
https://github.com/microsoft/Detours/blob/master/samples/member/member.cpp
That sample already defines the targets member function - but I dont I only know the offset in the binary im injecting my DLL into - so how do I convert this
void (CDetour::* CDetour::Real_Target)(void) =
(void (CDetour::*)(void))&CMember::Target;
to something like this:
void (CDetour::* CDetour::Real_Target)(void) =
(void (CDetour::*)(void))0xCAFEBABE;
I'm getting a compile error here
Any hints?
void (CDetour::* CDetour::Real_Target)(void) = (void (CDetour::*)(void))0xCAFEBABE;
I'm getting a compile error here
Specifically, it's error C2440: 'type cast' : cannot convert from 'unsigned int' to 'void (__thiscall CDetour::* )(void). There are no conversions from integral values to pointer-to-member values. Conversion to member pointers is a non-trivial beast - they may or may not be simple memory addresses, depending on the type of member function and complexity of the class hierarchy. Multiple virtual inheritance adds extra fields to this pseudo data structure; aside from the code address, there's also re-basing information. The format of this data is compiler-specific.
For my purposes, I use this MSVC-specific macro:
/// Void pointer to Func pointer.
/// Assumes first four bytes should hold the address and rest be zero.
template<typename T> T VTOF(void* ptr)
{// fills in 4 bytes and zeroes the rest
T result = 0;
*(void**)&result = ptr;
return result;
}
Usage: ptr = VTOF<void (CDetour::*)(void)>((void*)0xCAFEBABE);
Now, this obviously won't work in real complex code, but I assume it'll be good enough to work in a call to the original in a hook. It's been a while since I've had to use this on member function pointers.