V8 FunctionTemplate Class Instance - c++

I have the following class:
class PluginManager
{
public:
Handle<Value> Register(const Arguments& args);
Handle<ObjectTemplate> GetObjectTemplate();
};
I want the Register method to be accessible from JavaScript. I add it to the global object like this:
PluginManager pluginManagerInstance;
global->Set(String::New("register"), FunctionTemplate::New(pluginManagerInstance.Register));
It throws the following error:
'PluginManager::Register': function
call missing argument list; use
'&PluginManager::Register' to create a
pointer to member
I tried to do that, but it doesn't work either. And it's not correct, because I want it to call the Register method of the pluginManagerInstance.
Except for making the Register method static or global, any ideas?
Thanks.

You're trying to bind two things at once: the instance and the method to invoke on it, and have it look like a function pointer. That unfortunately doesn't work in C++. You can only bind a pointer to a plain function or a static method. So image you add a static "RegisterCB" method and register it as the callback:
static Handle<Value> RegisterCB(const Arguments& args);
...FunctionTemplate::New(&PluginManager::RegisterCB)...
Now where do you get the pluginManagerInstance from? For this purpose, most callback-registration apis in V8 have an additional "data" parameter that will get passed back to the callback. So does FunctionTemplate::New. So you actually want to bind it like this:
...FunctionTemplate::New(&PluginManager::RegisterCB,
External::Wrap(pluginManagerInstance))...
The data is then available through args.Data() and you can delegate to the actual method:
return ((PluginManager*)External::Unwrap(args.Data())->Register(args);
This can surely be made a little easier with some macro.

You will likely need to make it static. Don't forget member functions take a hidden this parameter as the first argument. Because of this, they rarely work well as function pointer prototypes.

For an example take a look at the code in this tutorial. The same method mernst suggests above is used to send a pointer to this object, to the log function.
in header:
virtual void log(const string &str);
static Handle<Value> logCallback(const Arguments &args);
Local<FunctionTemplate> makeStaticCallableFunc(InvocationCallback func);
Local<External> classPtrToExternal();
////////////////////////////////////////////////////////////////////////
//
// Converts an External to a V8TutorialBase pointer. This assumes that the
// data inside the v8::External is a "this" pointer that was wrapped by
// makeStaticCallableFunc
//
// \parameter data Shoudld be v8::Arguments::Data()
//
// \return "this" pointer inside v8::Arguments::Data() on success, NULL otherwise
//
////////////////////////////////////////////////////////////////////////
template <typename T>
static T *externalToClassPtr(Local<Value> data)
{
if(data.IsEmpty())
cout<<"Data empty"<<endl;
else if(!data->IsExternal())
cout<<"Data not external"<<endl;
else
return static_cast<T *>(External::Unwrap(data));
//If function gets here, one of the checks above failed
return NULL;
}
implementation:
////////////////////////////////////////////////////////////////////////
//
// Wrap a callback function into a FunctionTemplate, providing the "this"
// pointer to the callback when v8 calls the callback func
//
// \parameter func Static callback to be used in FunctionTemplate
//
// \return Local<FunctionTemplate> containing func
//
////////////////////////////////////////////////////////////////////////
Local<FunctionTemplate> V8TutorialBase::makeStaticCallableFunc(InvocationCallback func)
{
HandleScope scope;
Local<FunctionTemplate> funcTemplate = FunctionTemplate::New(func, classPtrToExternal());
return scope.Close(funcTemplate);
}
////////////////////////////////////////////////////////////////////////
//
// Makes the "this" pointer be an external so that it can be accessed by
// the static callback functions
//
// \return Local<External> containing the "this" pointer
////////////////////////////////////////////////////////////////////////
Local<External> V8TutorialBase::classPtrToExternal()
{
HandleScope scope;
return scope.Close(External::New(reinterpret_cast<void *>(this)));
}
Handle<Value> V8TutorialBase::logCallback(const Arguments &args)
{
HandleScope scope;
.....
V8TutorialBase *objPtr = externalToClassPtr<V8TutorialBase>(args.Data());
String::Utf8Value val(Local<String>::Cast(args[0]));
objPtr->log(*val); // log is a non static member function
// or you can directly do anything that you would do in a member function using the objPtr
return v8::Null();
}

If you want to call that method, you have to add parentheses:
lobal->Set( String::New("register")
, FunctionTemplate::New(pluginManagerInstance.Register()) );
^^
If you want to take its address, you have to add a &:
lobal->Set( String::New("register")
, FunctionTemplate::New(&PluginManager::Register) );
^
(Which is exactly what the error message says.)

Related

How can i pass a function as a function parameter in another function?

I am trying to use an Arduino library and to use one of it's functions as a parameter in my own function, but I don't know how can I do that.
I tried the code below but I get an error.
Any help will be appreciated.
P.S: I do not have an option to use auto keyword.
using namespace httpsserver;
HTTPServer Http;
typedef void (*Register)(HTTPNode*); // My typedef
Register Node = Http.registerNode;
When I am trying to call Node (...), I get the error below.
Cannot convert 'httpsserver::ResourceResolver::registerNode'
from type 'void (httpsserver::ResourceResolver::)(httpsserver::HTTPNode*)'
to type 'Register {aka void (*)(httpsserver::HTTPNode*)}'
How can I create a function pointer for the type :
'void (httpsserver::ResourceResolver::)(httpsserver::HTTPNode*)'
I want to use it as a parameter in another function:
// My Declaration
void Get(void(*Register)(httpsserver::HTTPNode*), const std::string& path);
// Usage
Get (Http.registerNode(...), ""); // Like so
How can I do that?
A member function pointer is not a function pointer.
typedef void (httpsserver::*Register)(HTTPNode*); // My typedef
Register Node = &httpsserver::registerNode;
usage:
void Get(void(httpsserver::*Register)(httpsserver::HTTPNode*), const std::string& path);
Get (&httpsserver::registerNode, "");
you have to pass the httpsserver::HTTPNode* into Register within Get.
If you want to bind the arguments to the function object and call it later, you want std::function<void()>:
void Get(std::function<void()>, const std::string& path);
Get ([&]{ Http.registerNode(...); }, "");
note, however, that this makes lifetime of the objects refered to within the {} above quite dangerous.

Is this defining a lambda function and assigning the function pointer to a value at the same time?

Still many C++ codes are so difficult for me to understand..
Below is a code snippet from dlib (http://dlib.net file : dlib/external/pybind11/include/pybind11/pybind11.h)
It's a member function definition of class cpp_function and I didn't try to understand the code(no time to do that..that's sad..). I can't understand the syntax in the line I put *** this line! comment at below. I understand the lambda function(unnamed function), so is it assigning a function pointer to rec->impl, the function taking function_call &call as argument and returning handle? So, it looks like defining a function and at the same time assigning the function pointer to a variable. Having asked it, it looks so now.. Please someone confirm this.
void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) {
using namespace detail;
struct capture { remove_reference_t<Func> f; };
...
rec->impl = [](function_call &call) -> handle { // <=== *** this line!
cast_in args_converter;
/* Try to cast the function arguments into the C++ domain */
if (!args_converter.load_args(call))
return PYBIND11_TRY_NEXT_OVERLOAD;
/* Invoke call policy pre-call hook */
process_attributes<Extra...>::precall(call);
/* Get a pointer to the capture object */
auto data = (sizeof(capture) <= sizeof(call.func.data)
? &call.func.data : call.func.data[0]);
capture *cap = const_cast<capture *>(reinterpret_cast<const capture *>(data));
/* Override policy for rvalues -- usually to enforce rvp::move on an rvalue */
const auto policy = return_value_policy_override<Return>::policy(call.func.policy);
/* Function scope guard -- defaults to the compile-to-nothing `void_type` */
using Guard = extract_guard_t<Extra...>;
/* Perform the function call */
handle result = cast_out::cast(
std::move(args_converter).template call<Return, Guard>(cap->f), policy, call.parent);
/* Invoke call policy post-call hook */
process_attributes<Extra...>::postcall(call, result);
return result;
};
...
using FunctionType = Return (*)(Args...);
constexpr bool is_function_ptr =
std::is_convertible<Func, FunctionType>::value &&
sizeof(capture) == sizeof(void *);
if (is_function_ptr) {
rec->is_stateless = true;
rec->data[1] = const_cast<void *>(reinterpret_cast<const void *>(&typeid(FunctionType)));
}
}
rec->impl = [](function_call &call) -> handle
creates a lambda which takes one argument of type function_call and returns a handle, then assigns it to rec->impl.
As lambdas are basically unnamed structs, they also have unnamed types. Since rec->impl obviously exists already and is thus not templatized on the lambda type, the lambda gets converted to some other type during the assignment. (Note: there could however be a templatized and overloaded operator= here)
Typically such types which can take lambdas are either std::function or function pointers as stateless lambdas can be converted to function pointers.

Is it possible to pass a member function to QueueUserAPC?

is there a possibility or a workaround to pass a member function to the Windows API function QueueUserAPC()?
Okay, I could pass a static member function.
But then I won't have full access to local member variables...
So is there a possibility to combine both, passing as member function and full access to non-static member variables?
I tried to work out a solution related to this but without any success yet.
Hopefully someone got an idea to solve this.
This is a kind of standard pattern to use when having C-style callbacks call your C++ functions.
You create a free function (or static member) that forwards the call ...
VOID CALLBACK ForwardTo_MyClass_func( _In_ ULONG_PTR dwParam )
{
auto* p = (MyClass*)dwParam;
p->func();
}
... and you then set it up by passing the instance pointer as the third parameter to QueueUserAPC:
QueueUserAPC( ForwardToMyClass_func, hThread, (ULONG_PTR)pMyClass );
If you need further arguments, you will have to create some kind of structure to hold both the instance pointer and the arguments.
The answer is no.
Windows API has a C interface, and therefor cannot handle name mangled signatures, such as C++ member functions. The function you pass must be a C style free function.
By the way, nesting it in a namespace is acceptable, if less scalable:
namespace apc_stuff
{
static MyStruct some_static_data;
static void __stdcall MyApcFunc(ULONG_PTR data); // PAPCFUNC
};
using namespace apc_stuff;
MyClass::DoSomething(...)
{
auto my_data = new MyData(...);
auto data = reinterpret_cast<ULONG_PTR>(my_data);
QueueUserAPC(MyApcFunc, hThread, data)
}
/*static*/ void __stdcall apc_stuff::MyApcFunc(ULONG_PTR data)
{
auto my_data = reinterpret_cast<MyData *>(data);
//
// use my_data
// use some_static_data
//
}

Cannot call member function without object = C++

I am brushing up again and I am getting an error:
Cannot call member function without object.
I am calling like:
FxString text = table.GetEntry(obj->GetAlertTextID());
FxUChar outDescription1[ kCP_DEFAULT_STRING_LENGTH ];
IC_Utility::CP_StringToPString(text, &outDescription1[0] );
The line: IC_Utility::CP_StringToPString(text, &outDescription1[0] ); is getting the error
My function is:
void IC_Utility::CP_StringToPString( FxString& inString, FxUChar *outString)
{
}
I know it has to be something simple I am missing.
If you've written the CP_StringToPString function, you need to declare it static:
static void IC_Utility::CP_StringToPString( FxString& inString, FxUChar *outString)
Alternatively, if it's a function in third-party code, you need to declare an IC_Utility object to call it on:
IC_Utility u;
u.CP_StringToPString(text, &outDescription1[0] );
Your method isn't static, and so it must be called from an instance (sort of like the error is saying). If your method doesn't require access to any other instance variables or methods, you probably just want to declare it static. Otherwise, you'll have to obtain the correct instance and execute the method on that instance.
You have to declare the function with the 'static' keyword:
class IC_Utility {
static void CP_StringToPString( FxString& inString, FxUChar *outString);
You need to declare the function static in your class declaration. e.g.
class IC_Utility {
// ...
static void CP_StringToPString(FxString& inString, FxUChar *outString);
// ...
};
"static" is the right answer. or, you can pass it a NULL "this" pointer if it's not used in the function:
((IC_Utility*)NULL)->CP_StringToPString(...);

I am new to threads, What does this compile error mean?

Using C++.
pthread_t threads[STORAGE]; // 0-99
...
void run()
Error>>> int status = pthread_create(&threads[0], NULL, updateMessages, (void *) NULL);
if (status != 0)
{
printf("pthread_create returned error code %d\n", status);
exit(-1);
}
...
void ClientHandler::updateMessages(void *)
{
string reqUpdate = "91"; // Request for update
string recvMSG;
while (true)
{
sleep(5);
sending(sock,reqUpdate); // send
recvMSG = receiving(sock); // receive
QString output(recvMSG);
emit signal_chat(output, 0); // Print message to text box
}
}
...
Compile Error:
TCPClient.cpp:109: error: argument of type ‘void (ClientHandler::)(void*)’ does not match ‘void* (*)(void*)’
I can't figure out whats wrong.
Thanks in advance.
A pointer to a member function is different from a global function with the same signature since the member function needs an additional object on which it operates. Therefore pointers to these two types of functions are not compatible.
In this case this means that you cannot pass a member function pointer to pthread_create but only a pointer to a non-member (or static) function. A work around for this problem is to use the forth parameter of pthread_create to pass a pointer to a object to a global function which then calls the method of the passed object:
class ClientHandler {
public:
void updateMessages();
void run();
};
// Global function that will be the threads main function.
// It expects a pointer to a ClientHandler object.
extern "C"
void *CH_updateMessages(void *ch) {
// Call "real" main function
reinterpret_cast<ClientHandler*>(ch)->updateMessages();
return 0;
}
void ClientHandler::run() {
// Start thread and pass pointer to the current object
int status = pthread_create(&threads[0], NULL, CH_updateMessages, (void*)this);
...
}
It's nothing to do with threads, it's a normal C++ error, you're just passing an incompatible type of function pointer.
A function pointer is not the same as a member instance function pointer, even if their signature is the same; this is because there is an implicit reference to *this passed. You can't avoid this.
As pthread_create takes a free function, create a static function(is a free function) inside ClientHandler
static void Callback(void * this_pointer,int other_arg) {
ClientHandler* self = static_cast< ClientHandler*>(this_pointer);
self-> updateMessages(other_arg);
}
and call pthread_create as follows
pthread_create(&threads[0], NULL, &ClientHandler::Callback, (void *) pointer_to_ClientHandler,int other_arg);
That works because Callback is free function
YoLinux has a nice pthread tutorial that my help you in learning about threads.
As others have already said, the problem is that the signatures between the functions are different. Class member functions always have a "secret" extra parameter, the this pointer. So you can never pass a member function where a global function is expected. You can hack around this either with libraries such as Boost.Bind, or by making the function a static member of the class.
But the simplest, and most elegant solution is to use a different threading API.
Boost.Thread is a very nice threading library for C++ (pthreads is designed for C, and that's why it doesnt play well with C++ features such as class methods).
I'd recommend using that.
Your code could be rewritten as something like this:
class ClientHandler {
public:
ClientHandler(/* All the parameters you want to pass to the thread. Unlike pthreads you have complete type safety and can pass as many parameters to this constructor as you like */){...}
void operator()() // boost.thread calls operator() to run the thread, with no parameters. (Since all parameters were passed in the constructor and saved as member variables
{
string reqUpdate = "91"; // Request for update
string recvMSG;
while (true)
{
sleep(5);
sending(sock,reqUpdate); // send
recvMSG = receiving(sock); // receive
QString output(recvMSG);
emit signal_chat(output, 0); // Print message to text box
}
}
// whatever arguments you want to pass to the thread can be stored here as member variables
};
boost::threead_group gr; // can store all your threads here, rather than being limited to your fixed-size array
gr.create_thread(ClientHandler(/* construct a ClientHandler object with the parameters you like*/));
You're passing a member function instead of a global, normal, one.
Just define:
void updateMessages(void *) {
static ClientHandler c;
// use c..
}