Converting std::function to a c-style function pointer?

closed account (3hM2Nwbp)
I've been banging my head against the wall for a good long while on this one...

1
2
3
4
5
6
7
8
9
10
11

void dummy(void* (*f)(void*))
{
  // Use f to start some threads, start a timer, launch the nukes, etc
}

std::function<void*(void*)> func;

auto magic = // insert magic here to convert func to (void* (*f)(void*);

dummy(magic);


Any help would be appreciated...I can't believe that Google has failed me this time.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void foo( std::function< void* (void*) > func )
{
    if( func ) // if the call-wrapper has wrapped a callable object
    {
        typedef void* function_t( void* ) ;
        function_t* ptr_fun = func.target<function_t>() ;
        if( ptr_fun != nullptr )
        {
            // the call-wrapper has wrapped a free function
            // and ptr_fun is a pointer to that function
            // use ptr_fun
        }
        else
        {
            // the callable object wrapped by the call-wrapper is not a free function of this type
            // it is a closure, a function object, a bind expression, or a free function with a 
            // different (though compatible) type - for example: int* function_type( const void* ) ;
            
        }
    }
}

Last edited on
closed account (3hM2Nwbp)
Excellent, thank you. If you don't mind my asking, where did you find the information about std::function to make that example from?

* Also, is there a way to convert a closure into a raw function pointer?

Normally, I would simply use boost::thread for what I'm trying to do, but I cannot in this case. What I'm trying to do is make a common, simple wrapper interface for encapsulating posix and win32 threads. I would have hoped to just use std::function to accomplish this...but as expected, it's fighting me as hard as it can.
Last edited on
I remembered the target() member function from pre-standardization discussions on comp.std.c++. Also looked at the FDIS now to confirm it.

Documentation for std::function<> should be available on the web at several places. Just Googled and got this: http://msdn.microsoft.com/en-us/library/bb982088.aspx



> * Also, is there a way to convert a closure into a raw function pointer?

If there is no lambda-capture, a closure can be implicitly converted to a pointer to function with the same parameter and return types. This was a late addition to the IS, so you may need to check if the compiler is conforming.

1
2
3
4
5
6
7
int bar( int (*pfn)( char ) ) { return pfn('A') ; }

int main()
{
    auto closure = [] ( char c ) { return +c ; } ;
    std::cout << bar( closure ) << '\n' ;
}

Last edited on
closed account (3hM2Nwbp)
Alright...I'll need to read up on GCC's documentation (again) to see if there are any unresolved issues with this, as I'm getting odd results. It seems like I'm doing more research to form workarounds than actually getting the project done. How I miss only targeting Windows systems..

Thanks again.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

class Thread
{
  public:
    Thread(std::function<void(void)> fn)
    {
      typedef void fn_type(void);
      std::cout << fn.target<fn_type>() << std::endl; // <-- Always nullptr
    }
};

void dummy(void)
{
  return nullptr;
}

int main()
{
  Thread t(dummy);
  return 0xBADC0DE;
}


I'm about ready to forget about making it elegant and scattering preprocessor macros through the source to get it working. :-\
Last edited on
Yeah, just tested it with GCC 4.7 and std::function<>::target() appears to be buggy.

Conversion from closure to pointer to function works as expected.
closed account (3hM2Nwbp)
So scattered preprocessor macros it is!

*shudders*

Thanks for all the help.
Ahh... Horrible mistake on my part, GCC is right and I was wrong. Dreadfully sorry about it.

The target is a pointer to a function, so function<.>::target() returns a pointer to a pointer to a function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void foo( std::function< void* (void*) > func )
{
    if( func ) // if the call-wrapper has wrapped a callable object
    {
        typedef void* function_t( void* ) ;
        function_t** ptr_ptr_fun = func.target<function_t*>() ;
        if( ptr_ptr_fun != nullptr )
        {
            function_t* ptr_fun = *ptr_ptr_fun ;
            ptr_fun(nullptr) ;
        }
    }
}

void* test_it( void* p ) { return std::cout << "ok!\n" ; }

int main()
{
    foo( test_it ) ;
}



Last edited on
Topic archived. No new replies allowed.