Open ayles opened 4 years ago
Tried to implement some kind of function selecting behaviour.
Gist.
So we're checking if arguments match for each passed function sequentially. On first match we're calling and just exiting with true
returned, or if there was no match false
is returned.
I'm quite unfamiliar with templates but I think this idea is fine, so check it please...
Hi,
yes, there was such a request earlier in #41. The issue as I see, is the overloaded functions dispatching can be resolved only at run-time, since an overloaded C++ wrapped function can be invoked in JavaScript with any argument list.
So a generic f(v8::FunctionCallbackInfo<v8::Value> const& args)
would lookup a suitable C++ function in a registry of overloads.
Current class_
implementation sets a wrapped function value in the class prototype template. Unfortunately, v8::Template
has no API to get previously set value, so for overloaded functions v8pp::class_
instance would have to track the function names, in order to replace overloaded ones with a generic dispatching version. And this tracking is required only on the class binding step.
Hmm, I tried to implement simple function wrapping this morning. And it works. Use looks like this:
void f(int a) {
std::cerr << "One int arg: " << a << std::endl;
}
void f(int a, int b) {
std::cerr << "Two int args: " << a << " " << b << std::endl;
}
void f(std::string s) {
std::cerr << "String arg: " << s << std::endl;
}
...
// binding (static_cast here used as hint to compiler, functions with names `f1` `f2` `f3` can be bound just by passing name)
context->Global()->Set(context, v8_str("test"),
v8b::wrap_function(isolate,
static_cast<void(*)(int, int)>(f),
static_cast<void(*)(int)>(f),
static_cast<void(*)(std::string)>(f)
)->GetFunction(context).ToLocalChecked()
);
...
// usage (in js)
test(1);
test(1, 3);
test("str");
Output will be
One int arg: 1
Two int args: 1 3
String arg: str
How it works:
On function template creation I'm passing v8::External
with array of void *
pointers to all passed functions.
Then I'm binding handler that is result of calling template function get_handler
that accepts all passed functions along with their signatures in templates. get_handler
builds handler that sequentially will compare args passed from js and functions signatures:
arguments_traits<typename function_traits<F>::arguments>::is_match(info)
And if there is match, it gets function pointer with current index from info.Data()
, casts it and calls with converted arguments.
So this approach is half-runtime half-compiletime (and it relies on template instantiation recursion =), and for any functions sequence passed will be generated new handler, but it is quite fast and requires no runtime type checks...
I hope you get the idea, because my English is very bad.
Now I see that it will be hard to just add this functionality to v8pp
, it is easier just to rewrite it from scratch...
Thanks for sharing the idea!
I haven't thought before to use an array of functions with the same name for single wrap_function()
call.
Hi again)
Started implementing ideas inspired by your lib here: https://github.com/ayles/v8bind
I'll later add link to v8pp
in README.
Class member variables binding and multiple constructors binding works fine,
will add function overloads binding later.
Hi,
thanks for sharing, and good luck with all your ideas!
Sincerely, Pavel
пт, 6 сент. 2019 г. в 00:36, Alexander Seleznev notifications@github.com:
Hi again) Started implementing ideas inspired by your lib here: https://github.com/ayles/v8bind I'll later add link to v8pp in README. Class member variables binding and multiple constructors binding works fine, will add function overloads binding later.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/pmed/v8pp/issues/125?email_source=notifications&email_token=AAISAUVECSREGHR3TVXWCPDQIGCX5A5CNFSM4ISOJYUKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6BBF2I#issuecomment-528618217, or mute the thread https://github.com/notifications/unsubscribe-auth/AAISAUXWQBZ7BUTNA3ESPJDQIGCX5ANCNFSM4ISOJYUA .
I'm also intrested in possibility of setting functions and constructors like:
Then best match will be selected. As far as I understand adding two or more functions is not as difficult as selecting wich one to use, cause here should be some rules like:
First, try find handler with same argument count. Second, try find exact argument type match. If there is no such handler, ...? In any other case select handler with
(const FunctionCallbackInfo &)
signature if available.So, is it possible and do you have any thoughts about it?