C++ Trying to Get Function Address from a Std::Function

C++ trying to get function address from a std::function

You need to use the template keyword when you call target:

#include <functional>
#include <iostream>

template<typename T>
size_t getAddress(std::function<void (T &)> f) {
typedef void (fnType)(T &);
fnType ** fnPointer = f.template target<fnType*>();
return (size_t) *fnPointer;
}

void foo(int& a) {
a = 0;
}

int main() {
std::function<void(int&)> f = &foo;
std::cout << (size_t)&foo << std::endl << getAddress(f) << std::endl;
return 0;
}

Hint: When you have problems with C++ syntax, I suggest you use clang++ to compile your code. If you play around with how your write the code it will usually point you in the write direction to fix the error (when it can figure out what you are doing).

I also suggest that you use variadic templates to make your function a bit more general:

template<typename T, typename... U>
size_t getAddress(std::function<T(U...)> f) {
typedef T(fnType)(U...);
fnType ** fnPointer = f.template target<fnType*>();
return (size_t) *fnPointer;
}

How do I get the address of a c-style function stored in an std::function?

Your version doesn't work because the answer you linked to is providing a wrapper around functions to provide a free-standing version you can use regardless of whether the source was a functor, function pointer or std::function.

In your case, you can use the target function of std::function:

void foo(){}

std::function<void()> f = foo;
auto fp = *f.target<void(*)()>();
auto bb = &foo;
printf("bb is %x\n", bb);
printf("fp is %x\n", fp);

Output:

bb is 80487e0
fp is 80487e0

C++ 11 get pointer of a std::function

I want to store and identify std::function objects in a std::map.

I assume, you want to identify std::function objects (e.g. to call or delete them selectively).
In such situations, I use an additional key e.g. a simple unsigned.
A global function may be used:

typedef unsigned Key;

Key genId()
{
static Key id = 0;
return ++id;
}

Now, the std::function objects can be paired with this key. The API may grant that access to paired std::function objects can be done using the key exclusively.

Call a C-style function address with std::bind and std::function.target using a method from object

This is a dirty little hack but should work

void foo(void(*f)(int)) {
f(2);
}

class TestClass {
public:
void foo(int i) {
std::cout << i << "\n";
}
};

static TestClass* global_variable_hack = nullptr;
void hacky_function(int x) {
global_variable_hack->foo(x);
}

int main() {

TestClass t;
global_variable_hack = &t;
foo(hacky_function);

return 0;
}

//can also be done with a lambda without the global stuff
int main() {
static TestClass t;
auto func = [](int x) {
t->foo(x); //does not need to be captured as it is static
};
foo(func); //non-capturing lambas are implicitly convertible to free functions
}

Get address of member function through std::bind?

You should switch to using std::function instead (update: it turns out you did already). std::function is a general-purpose polymorphic function wrapper that will accept raw function pointers, binds, etc.
That way you have a standardized way to compare, which you need to pull off somehow but std::function has ways to inspect the target, etc. : https://en.cppreference.com/w/cpp/utility/functional/function

Your signature becomes:

EventObject<Ts...>& operator-=(const std::function<R(Args...)>& rhs) {

Update: the issue with your target extraction is that you provide the signature of a plain function as the template argument - this will not work for the more 'advanced' function objects, binds etc. you have to provide the correct type so that:

target_type() == typeid(T)

see https://en.cppreference.com/w/cpp/utility/functional/function/target for more information and some relevant examples

Can I call a std::function from C?

The most portable method to interface between C/C++ will be to use pointers to pass data between languages and use non-member functions to make function calls.

The .h file:

#ifdef __cplusplus
extern "C" {
#endif

// Declare the struct.
struct Adder;

// Declare functions to work with the struct.
Adder* makeAdder(int amount);

int invokeAdder(Adder* adder, int n);

void deleteAdder(Adder* adder);

#ifdef __cplusplus
}
#endif

Implement them in a .cpp file as:

#include <functional>

typedef std::function<int(int)> AdderFunction;
struct Adder
{
AdderFunction f;
};

AdderFunction makeAdderFunction(int amount) {
return [amount] (int n) {
return n + amount;
};
}

Adder* makeAdder(int amount)
{
Adder* adder = new Adder;
adder->f = makeAdderFunction(amount);
return adder;
}

int invokeAdder(Adder* adder, int n)
{
return adder->f(n);
}

void deleteAdder(Adder* adder)
{
delete adder;
}

Can I take the address of a function defined in standard library?

Short answer

No.

Explanation

[namespace.std] says:

Let F denote a standard library function ([global.functions]), a standard library static member function, or an instantiation of a standard library function template.
Unless F is designated an addressable function, the behavior of a C++ program is unspecified (possibly ill-formed) if it explicitly or implicitly attempts to form a pointer to F.
[Note: Possible means of forming such pointers include application of the unary & operator ([expr.unary.op]), addressof ([specialized.addressof]), or a function-to-pointer standard conversion ([conv.func]).
— end note ]
Moreover, the behavior of a C++ program is unspecified (possibly ill-formed) if it attempts to form a reference to F or if it attempts to form a pointer-to-member designating either a standard library non-static member function ([member.functions]) or an instantiation of a standard library member function template.

With this in mind, let's check the two calls to std::invoke.

The first call

std::invoke(std::boolalpha, std::cout);

Here, we are attempting to form a pointer to std::boolalpha. Fortunately, [fmtflags.manip] saves the day:

Each function specified in this subclause is a designated addressable function ([namespace.std]).

And boolalpha is a function specified in this subclause.
Thus, this line is well-formed, and is equivalent to:

std::cout.setf(std::ios_base::boolalpha);

But why is that? Well, it is necessary for the following code:

std::cout << std::boolalpha;

The second call

std::cout << std::invoke(static_cast<ctype_func>(std::tolower), 'A') << "\n";

Unfortunately, [cctype.syn] says:

The contents and meaning of the header <cctype> are the same as the C standard library header <ctype.h>.

Nowhere is tolower explicitly designated an addressable function.

Therefore, the behavior of this C++ program is unspecified (possibly ill-formed), because it attempts to form a pointer to tolower, which is not designated an addressable function.

Conclusion

The expected output is not guaranteed.
In fact, the code is not even guaranteed to compile.


This also applies to member functions.
[namespace.std] doesn’t explicitly mention this, but it can be seen from [member.functions] that the behavior of a C++ program is unspecified (possibly ill-formed) if it attempts to take the address of a member function declared in the C++ standard library. Per [member.functions]/2:

For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected. [ Note: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name. — end note ]

And [expr.unary.op]/6:

The address of an overloaded function can be taken only in a context that uniquely determines which version of the overloaded function is referred to (see [over.over]). [ Note: Since the context might determine whether the operand is a static or non-static member function, the context can also affect whether the expression has type “pointer to function” or “pointer to member function”. — end note ]

Therefore, the behavior of a program is unspecified (possibly ill-formed) if it explicitly or implicitly attempts to form a pointer to a member function in the C++ library.

(Thanks for the comment for pointing this out!)

Get function pointer from std::function when using std::bind

This is quite impossible. The whole reason that std::function exists is that function pointers suck horrifically and should never, ever, be used by anyone, ever again, except for the doomed souls bearing the Burning Standards of Hell C interoperation, because they cannot handle functions with state.

A std::function<void()> cannot, in the general case, be converted to a void(*)(). The only reason this works in the first example is because it happens to be a void(*)() originally.

Get function address from a function structure member

Pointers to member functions are nothing like pointers to global functions or static member functions. There are many reasons for this, but I'm not sure how much you know about how C++ works, and so I'm not sure what reasons will make sense.

I do know that what you are trying in assembly simply won't work in the general case. It seems like you have a fundamental misunderstanding about the purpose of member functions and function pointers.

The thing is, you are doing some things that you would generally not do in C++. You don't generally build up tables of function pointers in C++ because the things you would use that sort of thing for are what virtual functions are for.

If you are determined to use this approach, I would suggest you not use C++ at all, and only use C.

To prove these pointer types are completely incompatible, here is a program for you:

#include <cstdio>

struct Foo {
int a;
int b;
int addThem() { return a + b; }
};

struct Bar {
int c;
int d;
int addThemAll() { return c + d; }
};

struct Qux : public Foo, public Bar {
int e;
int addAllTheThings() { return Foo::addThem() + Bar::addThemAll() + e; }
};

int addThemGlobal(Foo *foo)
{
return foo->a + foo->b;
}

int main()
{
int (Qux::*func)();

func = &Bar::addThemAll;
printf("sizeof(Foo::addThem) == %u\n", sizeof(&Foo::addThem));
printf("sizeof(Bar::addThemAll) == %u\n", sizeof(&Bar::addThemAll));
printf("sizeof(Qux::addAllTheThings) == %u\n", sizeof(&Qux::addAllTheThings));
printf("sizeof(func) == %u\n", sizeof(func));
printf("sizeof(addThemGlobal) == %u\n", sizeof(&addThemGlobal));
printf("sizeof(void *) == %u\n", sizeof(void *));
return 0;
}

On my system this program yields these results:

$ /tmp/a.out 
sizeof(Foo::addThem) == 16
sizeof(Bar::addThemAll) == 16
sizeof(Qux::addAllTheThings) == 16
sizeof(func) == 16
sizeof(addThemGlobal) == 8
sizeof(void *) == 8

Notice how the member function pointer is 16 bytes long. It won't fit into a void *. It isn't a pointer in the normal sense. Your code and union work purely by accident.

The reason for this is that a member function pointer often needs extra data stored in it related to fixing up the object pointer it's passed in order to be correct for the function that's called. In my example, when called Bar::addThemAll on a Qux object (which is perfectly valid because of inheritance) the pointer to the Qux object needs to be adjusted to point at the Bar sub-object before the function is called. So Qux::*s to member functions must have this adjustment encoded in them. After all, saying func = &Qux::addAllTheThings is perfectly valid, and if that function were called no pointer adjustment would be necessary. So the pointer adjustment is a part of the function pointer's value.

And that's just an example. Compilers are permitted to implement member function pointers in any way they see fit (within certain constraints). Many compilers (like the GNU C++ compiler on a 64-bit platform like I was using) will implement them in a way that do not permit any member function pointer to be treated as at all equivalent to normal function pointers.

There are ways to deal with this. The swiss-army knife of dealing with member function pointers is the ::std::function template in C++11 or C++ TR1.

An example:

 #include <functional>

// .... inside main
::std::function<int(Qux *)> funcob = func;

funcob can point at absolutely anything that can be called like a function and needs a Qux *. Member functions, global functions, static member functions, functors... funcob can point at it.

That example only works on a C++11 compiler though. But if your compiler is reasonably recent, but still not a C++11 compiler, this may work instead:

 #include <tr1/functional>

// .... inside main
::std::tr1::function<int(Qux *)> funcob = func;

If worse comes to worse, you can use the Boost libraries, which is where this whole concept came from.

But I would rethink your design. I suspect that you will get a lot more milage out of having a well thought out inheritance hierarchy and using virtual functions than you will out of whatever it is you're doing now. With an interpreter I would have a top level abstract 'expression' class that is an abstract class for anything that can be evaluated. I would give it a virtual evaluate method. Then you can derive classes for different syntax elements like an addition expression a variable or a constant. Each of them will overload the evaluate method for their specific case. Then you can build up expression trees.

Not knowing details though, that's just a vague suggestion about your design.

How do I compare a std::function's target with a member function's address?

function<?????> wrapper = bind(&Object::method, obj);

The bind expression returns a callable object that requires no arguments and returns void, so the logical call signature is void() and so you want std::function<void()>.

if (wrapper.target<?????>() == &Object::method) {

This won't work, because the function doesn't hold the pointer-to-member-function, it holds the result of the bind expression, which wraps the pointer-to-member-function.

The type returned by the bind expression (and therefore the type of the function's target) is some internal implementation detail such as _Binder<void, _Mem_fn<Object, void()>, Object*>, which you can't refer to directly.

You could do:

auto b = bind(&Object::method, obj);
function<void()> wrapper = b;
if (wrapper.target<decltype(b)>() != nullptr) {

But this doesn't tell you anything useful.



Related Topics



Leave a reply



Submit