I'm working on a Visual C++ 2010 Express console application.
Before I go into detail, the summary here is: How can I make an array/list/vector of functions and call them from that array?
So I'm having a little difficulty with function pointers. I'm writing a 'Terminal' class, which in turn has a member class 'CommandMap'. The purpose of the CommandMap class is to store a vector/array of functions and the strings that represent them in another vector/array. I want the functions to be called (only) when the class calls them from the vector, but it executed only when I added it to the vector and not when trying to call it.
I tried defining a type for it:
typedef void (*CmdCallback)();
I declared a vector to contain them:
vector<string> CmdNames;
vector<CmdCallback> CmdFuncs;
I add them like so:
// Map a new command
bool CommandMap::Map(string name, CmdCallback func)
{
if (!IsNullOrSpace(name) && func != NULL)
{
if (!Exists(name))
{
CmdNames.push_back(name);
CmdFuncs.push_back(func);
return true;
}
}
return false;
}
And I try calling them like this:
// Get a command callback from its identifier
CmdCallback CommandMap::GetFunc(string name)
{
int index = IndexOf(name);
if (index == -1) return NULL;
else return CmdFuncs.at(index);
}
// If the given string is a command indentifier
// it will invoke the associated callback.
bool CommandMap::Exec(string input)
{
for each (string id in CmdStrings)
{
if (input == id)
{
CmdCallback cmd;
cmd = GetFunc(id);
cmd();
return true;
}
}
return false;
}
I tried using this:
CmdCallback SayHello()
{
cout << "Hello World!" << endl;
return NULL; // Forces me to return null, guessing since it's
// not 'void' but a 'void' pointer it must return something
}
int main(int argc, char *argv[])
{
App = new Terminal(argc, argv);
App->Commands->Map("say", SayHello);
while (!App->ExecComplete)
{
App->WaitEnter();
App->Commands->Exec("say");
App->WaitEnter();
App->ExecComplete = true;
}
return App->ExitCode;
}
This works, at first. The function gets called when I try to Map() it though. And when I Exec() "say", it finds the callback, but when it tries to call it, I get this runtime error, to which I can see no detail other than the option to break or continue. The code it gives me is.
I pretty much want to abandon my method and try a new approach, maybe I'm going the wrong way with the void pointer typedef, and I need to throw a '&' or a '*' somewhere I haven't like in the Map() argument list. Maybe a vector isn't the best way to do this either.
Basically, I am asking how I can I make an array of functions that can (and only) be called by referencing them from the array. I'm terrible with callbacks.
You can use std::functions, or, if you don't have C++11 support, boost::function. These are function object wrappers that can be easily constructed from free or member functions. You can store these in a standard library container or simple array.
If I understand correctly you actually want to declare SayHello as void SayHello() so that a pointer to SayHello has the type void (*)() (i.e. CmdCallback) which is what you need for your vector of functions.
Related
I was trying to assign a non-static function to a variable in C++.
I have two functions, which are onMessageReceived and enableCommand.
Here are definitions:
NetworkUtil.h:
class NetworkUtil{
public:
std::function<void(char* message)> onMessageReceived;
void enableCommand(char* cmd);
private:
// some private variables
}
NetworkUtil.cpp:
void NetworkUtil::enableCommand(char* cmd) {
if (strcmp(cmd, "INIT_ACK") == 0){
mCreateEnabled = true;
}
else if (strcmp(cmd, "START_ACK")){
mStartEnabled = true;
}
else{
std::cerr << "Unknown Command: " << cmd << std::endl;
}
}
Here is a program that assigns a function to a variable:
void NetworkUtil::onMessage(WebSocket* ws, const WebSocket::Data &data)
{
// not working
onMessageReceived = &(NetworkUtil::enableCommand);
// not working either
onMessageReceived = std::bind(&NetworkUtil::enableCommand, data.bytes);
}
I tried both, but non of them are working. Can I get some advice on assigning a non-static function to a variable?
Try to do like this:
onMessageReceived = std::bind(&NetworkUtil::enableCommand, this, _1);
Since you're using std::function (hence C++11 or later), I assume you can give lambda functions a try:
// Create a local variable for capturing purposes.
// You must make sure the source data is never outlived by the callback
// to avoid the "use after free" scenario.
auto bytes = data.bytes;
onMessageReceived = [=](char * message) { this->enableCommand(bytes); };
= means to capture everything actually used by the closure by value (including the value of the this pointer), and due to use of type erasure you can assign it to a signature-compatible std::function.
Im trying to remove pairs from vector with remove_if, but im getting errors
bool MyClass::isSingleTag(const pair<int,string> & val) {
string tag = val.second;
int posImg, posBr;
posImg = tag.find("<img");
posBr = tag.find("<br");
if (posImg == -1 && posBr == -1) {
return false;
} else {
return true;
}
}
void MyClass::deleteSingleTags() {
vector<pair<int,string>>::iterator last_iter;
last_iter = remove_if(allTags.begin(), allTags.end(), &MyClass::isSingleTag);
allTags.erase(last_iter, allTags.end());
}
Errors: http://pastebin.com/1FCWRVDG
A pointer to a member function isn't callable without an object of the class the function is member of.
Make isSingleTag static - taking its address results in a plain function pointer. Alternatively, make it a free function, since it looks like it's got no bussiness being a member function in the first place (it doesn't access any other members, does it?).
The other option (for when you legitimately need to be a member function) is to bind it to a class object, using std::bind:
MyClass obj;
auto func = std::bind(&MyClass::isSingleTag, obj);
Now func is a callable that you can pass to the algorithm.
So I am unsure why this wont work, ive tried some googling, i just cant find out what the problem is
void Player::Cmd(std::vector<std::string> &tokens)
{
std::string str = tokens[0];
std::map<std::string, void (Player::*)()>::iterator it = playerCommands.find(str);
Func fun;
if (it != playerCommands.end())
{
fun = it->second; //i tried it->second(); same issue
fun(); //error C2064: term does not evaluate to a
//function taking 0 arguments
}
else
{
std::cout << "What? \n";
}
}
git hub for the project
https://github.com/lordkuragari/TextRPG
Contrary to your belief, your map doesn't hold function pointers. So you cannot call the elements in the map.
Rather, your map contains pointers to member functions. Non-static member functions aren't functions and cannot be called; rather, they have to be invoked on an object. You can invoke a member function on an object given by a pointer p via a function pointer ptfm like this:
(p->*ptmf)();
In your case, presumably you want to use p = this and ptfm = fun, so it'd be:
(this->*fun)();
Or, without the local variable:
(this->*it->second)();
In C++17 you can also use std::invoke(it->second, this).
I am creating a wrapper class that wraps a bunch of functions outlined in a particular 3rd party API. When I try to wrap non-member functions like this:
(AVTcamDllWrapper.h)
typedef VmbErrorType (WINAPI * AVTGETCAMERAS) (CameraPtrVector cameras);
class CAVTcamDllWrapper
{
HMODULE mAVTCamLibrary; //I later have this point to the DLL
public:
void AVTGetCameras (CameraPtrVector cameras);
};
(AVTcamDllWrapper.cpp)
void CAVTcamDllWrapper::AVTGetCameras(AVTNS CameraPtrVector cameras)
{
AVTGETCAMERAS pFunc = NULL;
pFunc = (AVTGETCAMERAS) GetProcAddress(mAVTCamLibrary, "?GetCameras#VimbaSystem#VmbAPI#AVT##AEAA?AW4VmbErrorType##PEAV?$shared_ptr#VCamera#VmbAPI#AVT###23#AEAI#Z");
DWORD dw = GetLastError();
if(pFunc == NULL)
{
Exlog(L"CAVTcamDllWrapper::AVTGetCameras: Failed to locate AVTGetCameras method in AVTCamera DLL.");
NIERR_SET_AND_THROW_ERROR(NIERR_CAMERA_ERROR, L"Failed to locate AVTGetCameras method in AVTCamera DLL.");
}
VmbErrorType vErr = pFunc(cameras);
if(vErr != VmbErrorSuccess)
{
wstring exLogMsg = Format(exLogMsg, L"CAVTcamDllWrapper::AVTGetCameras(): Failed to get any cameras. VmbErrorType = %d", vErr);
Exlog(exLogMsg.c_str());
NIERR_SET_AND_THROW_ERROR(NIERR_CAMERA_ERROR, L"Failed to get any cameras.");
}
}
The above code works great for non-member functions. For example, if I am trying to wrap a function that is called simply by saying:
CallFunction(blah, blaaaaah);
then the wrapper class works fine, and the pFunc is set properly and no error occurs on the VmbErrorType vErr = pFunc(); line;
However, many of my functions are member function, and are called like this:
SomeObject.CallMemberFunction(blah, bleh);
// or
SomeObjectPointer->CallMemberFunction(what, ever);
and these are the functions I can't seem to wrap. The error occurs on the line:
VmbErrorType vErr = pFunc();
because the function cannot be called without a specific object to call it from. In my example, I am wrapping a function GetCameras which exists inside of Camera. Without wrapping the function, to call it I simply create a vector of Camera pointers, and do:
cameras[0]->GetCameras(VmbAccessModeFull);
which works. But I have no idea how I would go about wrapping this function, as the call to GetCameras is both dependent on cameras[0] and completely useless without a camera to call it from.
So how do I wrap member functions like the one shown above?
Edit 1:
I have tried to pass in a reference to a specific object and do
VmbErrorType vErr = theObject->pFunc();
but obviously this won't work because then it will think to look for a function named pFunc inside of theObject, which doesn't exist.
Edit 2:
I feel like I would almost have modify the wrapper function to pass the reference object in as a parameter or something. So like instead of the regular:
cameras[0]->GetCameras(VmbAccessModeFull);
I would have to modify some stuff and make my wrapper function look like this:
mWrapperObject->WrappedGetCameras(VmbAccessModeFull, cameras[0]);
so that the wrapped function will have the context it needs to act as a member function.
To call a member function you must have an object at hand. To have an object you must get it from somewhere. The only place a good little well-behaving function can get stuff from is its parameter list.
So each of your functions obviously must have a parameter that receives The Object.
If you want your wrapper functions to be callable from C, you cannot have class types as function parameters. So you either declare it as a void* and do a cast inside, or just cheat and type it (for C only!) struct YourClassName* (without ever defining the struct). For C++, it should still use the class keyword. Use the preprocessor.
In a nutshell,
foo->bar(moo, roo)
is the fancy shmancy C++ way of saying
FooType_bar(foo, moo, roo)
and you should think about wrapping the latter while actually spelling the former.
How the caller obtains The Object then? One of your functions could create objects (with new) and return pointers to them. Another one could do a delete. Or you can return pointers to elements of a pre-allocated array. Or whatever. Basically you wrap the ways you use to obtain pointers to objects as a user of the original, unwrapped library.
That's about it.
You just need to pass the this pointer as first argument if you are calling memberfunctions and make sure you are using the right calling convention. For static member functions you don´t have to pass the this pointer.
On x64 you would not even have to worry about calling conventions, as everything will be compiled as __fastcall. No matter what calling convention you specify.
#include <iostream>
#include <stdint.h>
class Camera
{
int i;
public:
Camera()
{
i = 123;
}
void __stdcall print_1(int j, int k)
{
std::cout << i << j << k << std::endl;
}
void __cdecl print_2(int j, int k)
{
std::cout << i << j << k << std::endl;
}
void print_3(int j, int k)
{
std::cout << i << j << k << std::endl;
}
static void __cdecl print_s1(int j, int k)
{
std::cout << j << k << std::endl;
}
static void __stdcall print_s2(int j, int k)
{
std::cout << j << k << std::endl;
}
};
int main() {
Camera cam;
Camera* pCam = &cam;
// call __stdcall memberfunction
typedef void (__stdcall* tprint_1)(Camera*,int,int);
tprint_1 print_1 = (tprint_1)&Camera::print_1;
print_1(pCam,1,2);
// call __cdecl memberfunction
typedef void (__cdecl* tprint_2)(Camera*,int,int);
tprint_2 print_2 = (tprint_2)&Camera::print_2;
print_2(pCam,3,4);
// call __thiscall memberfunction
typedef void (__thiscall* tprint_3)(Camera*,int,int);
tprint_3 print_3 = (tprint_3)&Camera::print_3;
print_3(pCam,5,6);
// call __thiscall memberfunction different syntax
typedef void (Camera::* tprint_4)(int,int);
tprint_4 print_4 = (tprint_4)&Camera::print_3;
(pCam->*print_4)(7,8);
// static member functions don´t take a this pointer
typedef void(__cdecl* tprint_s1)(int,int);
tprint_s1 print_s1 = (tprint_s1)&Camera::print_s1;
print_s1(9,10);
// static member functions don´t take a this pointer
typedef void(__stdcall* tprint_s2)(int,int);
tprint_s2 print_s2 = (tprint_s2)&Camera::print_s2;
print_s2(11,12);
return 0;
}
You can do this by converthing the thiscall for memberfunctions to a fastcall
http://www.unknowncheats.me/forum/c-and-c/73849-thiscall-hooking.html
Here's how it's done. Say you have two layers: The member function layer and the wrapper function layer. What you need to do is create a third layer that lies in between these two layers, and export this layer to a .dll file. At first (back when I asked the question) I was trying to wrap functions that looked like this:
void SomeClass::SomeFunction(CString someParam)
{
//blah blah
}
This didn't work because, as the question describes, you cannot wrap member functions. What I discovered was that I needed to do all of the object management on a layer above the member function calls, but still below the wrapper functions. What I ended up with was a bunch of "Bridge" functions (that's what I called them) that "bridge" the gap between the wrapper functions and the member functions. So now, I wrapped functions that looked like this:
void BridgedSomeFunction(CString someParam)
{
classObject.SomeFunction(someParam);
}
Then I simply did some __declspec(dllexport)'s and __declspec(dllimport)'s to turn these functions into a .dll file, and that's it!
I have a class Test with a peculiar data structure.
A member of class Test is a std::map where the key is a std::string and the mapped value is a struct defined as follows:
typedef struct {
void (Test::*f) (void) const;
} pmf_t;
Initialization of the map is OK. The problem is when I am trying to call the function pointed. I made up a toy example reproducing the problem. Here it is:
#include <iostream>
#include <map>
using namespace std;
class Test;
typedef void (Test::*F) (void) const;
typedef struct {
F f;
} pmf_t;
class Test
{
public:
Test () {
pmf_t pmf = {
&Test::Func
};
m["key"] = pmf;
}
void Func (void) const {
cout << "test" << endl;
}
void CallFunc (void) {
std::map<std::string, pmf_t>::iterator it = m.begin ();
((*it).second.*f) (); // offending line
}
std::map<std::string, pmf_t> m;
};
int main ()
{
Test t;
t.CallFunc ();
return 0;
}
Thanks in advance,
Jir
The name of the pmf_t type is f, so the first change is to remove the * to get second.f. That gives you a pointer-to-member value. To use a pointer-to-member, you need an instance. The only one you have available of the correct type is this, so use it with the ->* operator:
(this->*it->second.f)();
You need parentheses around the whole thing, or else the compiler thinks you're trying to call it->second.f() (which isn't allowed) and then applying the result to ->*.
The offending line is trying to call a member function without any object to call it on. If the intention is to call it for the this object, I believe the call should look like
( this->* ((*it).second.f) )();
Where this->* is the syntax for dereferencing a pointer-to-member for the current object. ((*it).second.f) is the pointer retrieved from the map, and () is the call operator for actually calling the function.
This is perhaps good as an exercise, but otherwise of limited use.
I think you might want to check out the C++ FAQ on this one. The syntax is apparently pretty tricky to get right (they actually recommend using a macro).
It might be too late for this question but, the seemingly complex synatax can be break down to two simple lines so it looks pretty clear:
void CallFunc (void)
{
pmf_t t = m["key"]; //1>get the data from key
(this->*t.f)(); //2>standard procedure to call pointer to member function
}
try this:
(this->*((*it).second.f)) ();