I am working on a school assignment in which I need to build a thread library.
I need pc to hold the address of the given Thread object's run() function.
When I try to cast a member function pointer to address_t (which is really unsigned long int) I get this error
../main.cpp: In function ‘void setup(Thread&)’:
../main.cpp:77:22:
error: invalid cast from type ‘int (Thread::*)()’ to type ‘address_t
{aka unsigned int}’
make: * [main.o] Error 1
Here's the function where I get the error:
void setup(Thread &thread)
{
address_t sp, pc;
sp = (address_t)stack1 + STACK_SIZE - sizeof(address_t);
int (Thread::*temp)() = &Thread::run;
pc = (address_t) temp; // ## LINE 77 ##
sigsetjmp(jbuf[0],1);
(jbuf[0]->__jmpbuf)[JB_SP] = translate_address(sp);
(jbuf[0]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&jbuf[0]->__saved_mask);
}
A few clarification:
Thread is a class I wrote, currently doing nothing. It as a int run(void) as its "main" function. address_t, as I said, is typedef unsigned long int
Any ideas as to why I get this error? thanks
I don't think you can do that.
void pointers are pointers to data, and function pointers point to functions. The language does not require functions and data to be in the same address space, so, by way of example and not limitation, on architectures that have them in different address spaces, the two different pointer types will not be comparable.
Take a look at this nice faq. If you cannot convert to void*, then you cannot convert to int or long int
This doesn’t work for two reasons:
function pointers are not compatible with void* (se UmNyobe’s answer), and
in order to use member functions as the thread entry you’d need to store a this pointer as well.
Since you’re using C++ you’ve got a few possibilities though:
Use a base class thread_base defining a virtual function as the thread entry point.
Use a functor as the thread entry point.
In either case you’d need to store this information somewhere and invoke it using the operating system’s thread library.
Related
A 3rd party C library contains the following global variable and function:
typedef RtBasis float[4][4];
RI_EXPORT RtBasis RiCatmullRomBasis;
RI_EXPORT void RiBasis(RtBasis u);
I want to retrieve the variable and function from the DLL and use them in my C++ code. When I do the following:
// Get the function.
void (*RiBasis)(RtBasis);
RiBasis = (void (*)(RtBasis))GetProcAddress(h, "RiBasis");
// Get the variable.
RtBasis *RiCatmullRomBasis;
RiCatmullRomBasis = (RtBasis*)GetProcAddress(h, "RiCatmullRomBasis");
// Call the function, passing it the variable.
RiBasis(RiCatmullRomBasis);
Visual C++ gives this compile error on the call to RiBasis:
error C2664: 'void (float [][4])': cannot convert argument 1
from 'RtBasis (*)' to 'float [][4]'
I tried removing one level of indirection from the RiCatmullRomBasis variable:
// Get the variable.
RtBasis RiCatmullRomBasis;
RiCatmullRomBasis = (RtBasis)GetProcAddress(h, "RiCatmullRomBasis");
// Call the function, passing it the variable.
RiBasis(RiCatmullRomBasis);
but that gave me the following on the GetProcAddress call:
error C2440: 'type cast': cannot convert from 'FARPROC' to 'RtBasis'
note: There are no conversions to array types, although there are
conversions to references or pointers to arrays
What's the correct way of declaring the types in my C++ code to make this work?
In the first version make the call as:
RiBasis(*RiCatmullRomBasis);
You need to get the address of the variable (that is what GetProcAddress can return), but the function takes an instance rather than a pointer so you have to dereference the returned pointer.
This is perplexing. Using g++ 4.9.1:
int main()
{
void* r1 = __builtin_return_address(0); // fine
unsigned int foo = 0;
void* r2 = __builtin_return_address(foo); // does not compile
}
The error returned is error: invalid argument to ‘__builtin_return_address’
The documentation says that this function takes an unsigned int. I know the __builtin functions have all kinds of weirdness, and this just might be how life is, but I need to be able to step through this thing with an incrementing variable for a stack dumper I'm trying to implement. If it only accepts constant arguments, that's not really possible.
Is there a workaround or a better way?
Just make your own huge switch/case or if/else tree up to as many levels as you may need. You can use macros to make it simpler.
I am learning D and have mostly experience in C#. Specifically I am trying to use the Derelict3 Binding to SDL2. I have been able to get some basic functionality working just fine but I have become stumped on how to create an array argument for a specific call.
The library contains a call
SDL_RenderDrawLines(SDL_Renderer*, const(SDL_Point)*, int) //Derelict3 Binding
And I have been unable to correctly form the argument for
const(SDL_Point)*
The SDL Documentation for this function states that this argument is an array of SDL_Point, but I am unclear how to create an appropriate array to pass to this function.
Here is an example of what I have at the moment:
void DrawShape(SDL_Renderer* renderer)
{
SDL_Point a = { x:10, y:10};
SDL_Point b = { x:500, y:500};
const(SDL_Point[2]) points = [a,b];
Uint8 q = 255;
SDL_SetRenderDrawColor(renderer,q,q,q,q);
SDL_RenderDrawLines(renderer,points,1);
}
And the compiler complains that I am not passing the correct type of argument for const(SDL_Point)* in points.
Error: function pointer SDL_RenderDrawLines (SDL_Renderer*, const(SDL_Point)*, int)
is not callable using argument types (SDL_Renderer*, const(SDL_Point[2u]), int)
I suspect this is a fundamental misunderstanding on my part so any help would be appreciated.
Arrays aren't implicitly castable to pointers in D. Instead, each array (both static and dynamic) has an intrinsic .ptr property that is a pointer to its first element.
Change your code to:
SDL_RenderDrawLines(renderer,points.ptr,1);
given that the call asks for a pointer and length, I feel it is safer to define you own wrapper:
SDL_RenderDrawLines(SDL_Renderer* rend, const SDL_Point[] points){
SDL_RenderDrawLines(rend,points.ptr,points.length);
}
(why it isn't defined I don't know, any performance hit from the extra function call is just a -inline away from being resolved)
I looked at this excellent answer but can't figure out how to apply it to this snipped:
//this is in the .hpp file
std::atomic<int> size = 10;
std::recursive_mutex *locks[2];
//in some function of the class
//it's important that the 2nd array dimension is dynamic
the_lock[0] = new std::recursive_mutex[size];
the_lock[1] = new std::recursive_mutex[size];
std::recursive_mutex (*locks_2)[2][size] = &locks;
The assignment gives me
error: cannot convert ‘std::recursive_mutex* (*)[2]’ to ‘std::recursive_mutex (*)
[2][(((sizetype)(((ssizetype)((**here be long type information, since I'm using
templates a lot**, long unsigned int, std::less<long unsigned int>
>::size.std::atomic<long unsigned
int>::<anonymous>.std::__atomic_base<_IntTp>::operator
std::__atomic_base<_IntTp>::__int_type<long unsigned int>()) + -1)) + 1)]’ in
initialization
How can I obtain a pointer to 'locks'?
The error message is actually giving away the solution for free:
std::recursive_mutex * (*locks_2)[2] = &locks;
One can use the fact that this sort of thing has been officially declared to be ridiculously hard to get right for no apparent reason that the compiler cannot solve for you. If your compiler supports C++ 2011 that is. Use:
auto my_ptr = &locks; // point to locks, let the compiler worry about types
Requires that you compile your code as C++ 2011 though. (-std=c++11 for GCC).
locks is just an array of pointers. So you could use a pointer pointer to point to it.
std::recursive_mutex **locks_2 = locks;
I am running the same exact code that I ran in plain C:
pthread_create(&threads[i], &attr, SomeMethod, ptrChar);
And I get the errors:
error: invalid conversion from
'void*(*)(char'*)' to 'void*(*)(void*)'
error: initializing argument 3 of 'int
pthread_create(__pthread_t**,
__pthread_attr_t* conts*, void*(*)(void*), void*)'
SomeMethod is:
void *SomeMethod(char *direction)
Do I need to do something different in C++? I thought you could just run any C code in C++ and it would work fine?
I am using Cygwin at the moment.
Like it says, they are two different function signatures. You should do:
void *SomeMethod(void* direction) // note, void
{
char* dir = static_cast<char*>(direction); // and get the value
}
C was casting from one function pointer to the other, apparently. Casting one function pointer to another is undefined behavior in C++.
That said, I'm pretty sure POSIX requires that casts between function pointers be well-defined, so you may be able to do this instead:
pthread_create(&threads[i], &attr, // cast the function pointer
reinterpret_cast<void* (*)(void*)>(SomeMethod), ptrChar);
Your thread function needs to be:
void *SomeMethod(void *direction);
And you can cast from void* to char* inside the function.