-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implement c++ passthrough using n-api
- Loading branch information
1 parent
33e8c22
commit b4fafa6
Showing
6 changed files
with
364 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#include <node_api.h> | ||
#include "js-passthrough.h" | ||
|
||
napi_value Init(napi_env env, napi_value exports) { | ||
exports = PassThrough::CreateClass(env); | ||
|
||
return exports; | ||
} | ||
|
||
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"targets": [ | ||
{ | ||
"target_name": "addon", | ||
"sources": [ "addon.cc", "js-passthrough.cc" ] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
#include <node_api.h> | ||
#include <assert.h> | ||
#include <stdio.h> | ||
#include "js-passthrough.h" | ||
#include "utils-inl.h" | ||
|
||
napi_ref PassThrough::constructor; | ||
|
||
PassThrough::PassThrough() | ||
: source_(nullptr), sink_(nullptr), env_(nullptr), wrapper_(nullptr) {} | ||
|
||
PassThrough::~PassThrough() { napi_delete_reference(env_, wrapper_); } | ||
|
||
void PassThrough::Destructor(napi_env env, void* nativeObject, void* /*finalize_hint*/) { | ||
reinterpret_cast<PassThrough*>(nativeObject)->~PassThrough(); | ||
} | ||
|
||
#define DECLARE_NAPI_METHOD(name, func) \ | ||
{ name, 0, func, 0, 0, 0, napi_default, 0 } | ||
|
||
napi_value PassThrough::CreateClass(napi_env env) { | ||
napi_status status; | ||
napi_property_descriptor properties[] = { | ||
// { "value", 0, 0, GetValue, SetValue, 0, napi_default, 0 }, | ||
DECLARE_NAPI_METHOD("bindSource", BindSource), | ||
DECLARE_NAPI_METHOD("bindSink", BindSink), | ||
DECLARE_NAPI_METHOD("next", Next), | ||
DECLARE_NAPI_METHOD("pull", Pull), | ||
}; | ||
|
||
napi_value cons; | ||
status = | ||
napi_define_class(env, "PassThrough", NAPI_AUTO_LENGTH, New, nullptr, 4, properties, &cons); | ||
if (status != napi_ok) return nullptr; | ||
|
||
status = napi_create_reference(env, cons, 1, &constructor); | ||
if (status != napi_ok) return nullptr; | ||
|
||
assert(status == napi_ok); | ||
return cons; | ||
} | ||
|
||
napi_value PassThrough::New(napi_env env, napi_callback_info info) { | ||
napi_status status; | ||
|
||
napi_value target; | ||
status = napi_get_new_target(env, info, &target); | ||
assert(status == napi_ok); | ||
bool is_constructor = target != nullptr; | ||
|
||
if (is_constructor) { | ||
// Invoked as constructor: `new PassThrough(...)` | ||
napi_value jsthis; | ||
status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr); | ||
assert(status == napi_ok); | ||
// | ||
// double value = 0; | ||
// | ||
// napi_valuetype valuetype; | ||
// status = napi_typeof(env, args[0], &valuetype); | ||
// assert(status == napi_ok); | ||
// | ||
// if (valuetype != napi_undefined) { | ||
// status = napi_get_value_double(env, args[0], &value); | ||
// assert(status == napi_ok); | ||
// } | ||
|
||
PassThrough* obj = new PassThrough(); | ||
|
||
obj->env_ = env; | ||
status = napi_wrap(env, | ||
jsthis, | ||
reinterpret_cast<void*>(obj), | ||
PassThrough::Destructor, | ||
nullptr, // finalize_hint | ||
&obj->wrapper_); | ||
assert(status == napi_ok); | ||
|
||
return jsthis; | ||
} else { | ||
// Invoked as plain function `PassThrough(...)`, turn into construct call. | ||
size_t argc_ = 1; | ||
napi_value args[1]; | ||
status = napi_get_cb_info(env, info, &argc_, args, nullptr, nullptr); | ||
assert(status == napi_ok); | ||
|
||
const size_t argc = 1; | ||
napi_value argv[argc] = {args[0]}; | ||
|
||
napi_value cons; | ||
status = napi_get_reference_value(env, constructor, &cons); | ||
assert(status == napi_ok); | ||
|
||
napi_value instance; | ||
status = napi_new_instance(env, cons, argc, argv, &instance); | ||
assert(status == napi_ok); | ||
|
||
return instance; | ||
} | ||
} | ||
|
||
napi_value PassThrough::BindSource(napi_env env, napi_callback_info info) { | ||
napi_status status; | ||
|
||
size_t argc = 1; | ||
napi_value argv[argc]; | ||
napi_value jsthis; | ||
status = napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); | ||
assert(status == napi_ok); | ||
|
||
napi_value source = argv[0]; | ||
|
||
napi_value global; | ||
status = napi_get_global(env, &global); | ||
assert(status == napi_ok); | ||
PRINT_NAPI_TYPE(global, "0"); | ||
|
||
napi_value console; | ||
status = napi_get_named_property(env, | ||
global, | ||
"console", | ||
&console); | ||
assert(status == napi_ok); | ||
PRINT_NAPI_TYPE(console, "1"); | ||
|
||
napi_value log_; | ||
status = napi_get_named_property(env, | ||
console, | ||
"log", | ||
&log_); | ||
assert(status == napi_ok); | ||
PRINT_NAPI_TYPE(log_, "2"); | ||
|
||
napi_value console_args[1] = { source }; | ||
status = napi_call_function(env, | ||
console, | ||
log_, | ||
1, | ||
console_args, | ||
nullptr); | ||
assert(status == napi_ok); | ||
|
||
|
||
napi_value source_bindsink; | ||
status = napi_get_named_property(env, | ||
source, | ||
"bindSink", | ||
&source_bindsink); | ||
assert(status == napi_ok); | ||
PRINT_NAPI_TYPE(source_bindsink, "4"); | ||
|
||
napi_value argv_[1] = { jsthis }; | ||
status = napi_call_function(env, | ||
source, | ||
source_bindsink, | ||
1, | ||
argv_, | ||
nullptr); | ||
PRINT_NAPI_ERROR_MESSAGE(status, "source.bindSink()"); | ||
assert(status == napi_ok); | ||
|
||
PassThrough* obj; | ||
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj)); | ||
assert(status == napi_ok); | ||
|
||
napi_ref source_ref; | ||
status = napi_create_reference(env, source, 1, &source_ref); | ||
assert(status == napi_ok); | ||
|
||
obj->source_ = source_ref; | ||
|
||
return jsthis; | ||
} | ||
|
||
napi_value PassThrough::BindSink(napi_env env, napi_callback_info info) { | ||
napi_status status; | ||
|
||
size_t argc = 1; | ||
napi_value argv[argc]; | ||
napi_value jsthis; | ||
status = napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); | ||
assert(status == napi_ok); | ||
|
||
PassThrough* obj; | ||
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj)); | ||
assert(status == napi_ok); | ||
|
||
napi_ref sink_ref; | ||
status = napi_create_reference(env, argv[0], 1, &sink_ref); | ||
assert(status == napi_ok); | ||
|
||
obj->sink_ = sink_ref; | ||
|
||
return nullptr; | ||
} | ||
|
||
napi_value PassThrough::Next(napi_env env, napi_callback_info info) { | ||
napi_status status; | ||
|
||
size_t argc = 4; | ||
napi_value argv[argc]; | ||
napi_value jsthis; | ||
status = napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); | ||
assert(status == napi_ok); | ||
|
||
PassThrough* obj; | ||
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj)); | ||
assert(status == napi_ok); | ||
|
||
napi_value sink; | ||
status = napi_get_reference_value(env, obj->sink_, &sink); | ||
assert(status == napi_ok); | ||
|
||
napi_value sink_next; | ||
status = napi_get_named_property(env, | ||
sink, | ||
"next", | ||
&sink_next); | ||
assert(status == napi_ok); | ||
|
||
status = napi_call_function(env, | ||
sink, | ||
sink_next, | ||
4, | ||
argv, | ||
nullptr); | ||
assert(status == napi_ok); | ||
|
||
return nullptr; | ||
} | ||
|
||
napi_value PassThrough::Pull(napi_env env, napi_callback_info info) { | ||
napi_status status; | ||
|
||
size_t argc = 2; | ||
napi_value argv[argc]; | ||
napi_value jsthis; | ||
status = napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); | ||
assert(status == napi_ok); | ||
|
||
PassThrough* obj; | ||
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj)); | ||
assert(status == napi_ok); | ||
|
||
napi_value source; | ||
status = napi_get_reference_value(env, obj->source_, &source); | ||
assert(status == napi_ok); | ||
|
||
PRINT_NAPI_TYPE(source, "5"); | ||
|
||
napi_value source_pull; | ||
status = napi_get_named_property(env, | ||
source, | ||
"pull", | ||
&source_pull); | ||
assert(status == napi_ok); | ||
|
||
PRINT_NAPI_TYPE(source_pull, "5"); | ||
|
||
status = napi_call_function(env, | ||
source, | ||
source_pull, | ||
2, | ||
argv, | ||
nullptr); | ||
PRINT_NAPI_ERROR_MESSAGE(status, "10"); | ||
PRINT_NAPI_STATUS(status, "20"); | ||
// assert(status == napi_ok); | ||
|
||
return nullptr; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#ifndef JS_PASSTHROUGH_H_ | ||
#define JS_PASSTHROUGH_H_ | ||
|
||
#include <node_api.h> | ||
|
||
class PassThrough { | ||
public: | ||
PassThrough(); | ||
~PassThrough(); | ||
|
||
static napi_value CreateClass(napi_env env); | ||
|
||
static void Destructor(napi_env env, void* nativeObject, void* finalize_hint); | ||
|
||
private: | ||
static napi_value New(napi_env env, napi_callback_info info); | ||
static napi_value BindSource(napi_env env, napi_callback_info info); | ||
static napi_value BindSink(napi_env env, napi_callback_info info); | ||
static napi_value Next(napi_env env, napi_callback_info info); | ||
static napi_value Pull(napi_env env, napi_callback_info info); | ||
|
||
static napi_ref constructor; | ||
napi_ref source_; | ||
napi_ref sink_; | ||
napi_env env_; | ||
napi_ref wrapper_; | ||
}; | ||
|
||
#endif // JS_PASSTHROUGH_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#include <node_api.h> | ||
|
||
#define PRINT_NAPI_TYPE(value, str) \ | ||
{ \ | ||
napi_valuetype type; \ | ||
napi_status status = napi_typeof(env, value, &type); \ | ||
assert(status == napi_ok); \ | ||
\ | ||
if (type == napi_undefined) printf("%s - undefined\n", str); \ | ||
if (type == napi_null) printf("%s - null\n", str); \ | ||
if (type == napi_boolean) printf("%s - boolean\n", str); \ | ||
if (type == napi_number) printf("%s - number\n", str); \ | ||
if (type == napi_string) printf("%s - string\n", str); \ | ||
if (type == napi_symbol) printf("%s - symbol\n", str); \ | ||
if (type == napi_object) printf("%s - Object\n", str); \ | ||
if (type == napi_function) printf("%s - Function\n", str); \ | ||
if (type == napi_external) printf("%s - External\n", str); \ | ||
} | ||
|
||
#define PRINT_NAPI_STATUS(status, str) \ | ||
{ \ | ||
if (status == napi_ok) printf("%s - ok\n", str); \ | ||
if (status == napi_invalid_arg) printf("%s - invalid_arg\n", str); \ | ||
if (status == napi_object_expected) printf("%s - object_expected\n", str); \ | ||
if (status == napi_string_expected) printf("%s - string_expected\n", str); \ | ||
if (status == napi_name_expected) printf("%s - name_expected\n", str); \ | ||
if (status == napi_function_expected) printf("%s - function_expecte\n", str); \ | ||
if (status == napi_number_expected) printf("%s - number_expected\n", str); \ | ||
if (status == napi_boolean_expected) printf("%s - boolean_expected\n", str); \ | ||
if (status == napi_array_expected) printf("%s - array_expected\n", str); \ | ||
if (status == napi_generic_failure) printf("%s - generic_failure\n", str); \ | ||
if (status == napi_pending_exception) printf("%s - pending_exception\n", str); \ | ||
if (status == napi_cancelled) printf("%s - cancelled\n", str); \ | ||
} | ||
// if (status == napi_status_last) printf("%s - status_last\n", str); \ // ???? | ||
|
||
#define PRINT_NAPI_ERROR_MESSAGE(status, str) \ | ||
{ \ | ||
if (status != napi_ok) { \ | ||
const napi_extended_error_info* result; \ | ||
\ | ||
napi_get_last_error_info(env, &result); \ | ||
printf("%s - %s\n", str, result->error_message); \ | ||
} \ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters