Skip to content

Commit 35c8b60

Browse files
authored
Merge pull request #507 from goto-bus-stop/functions
Function calls
2 parents 661b5b4 + 0a40f6a commit 35c8b60

20 files changed

Lines changed: 775 additions & 103 deletions

File tree

crates/neon-runtime/src/nan/call.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub use neon_sys::Neon_Call_IsConstruct as is_construct;
1818
/// the function is bound to.
1919
pub use neon_sys::Neon_Call_This as this;
2020

21-
/// Mutates the `out` argument provided to refer to the `v8::Local` handle value of the
21+
/// Mutates the `out` argument provided to refer to the pointer value of the
2222
/// `v8::FunctionCallbackInfo` `Data`.
2323
pub use neon_sys::Neon_Call_Data as data;
2424

crates/neon-runtime/src/napi/call.rs

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::os::raw::c_void;
22
use std::ptr::null_mut;
33
use raw::{FunctionCallbackInfo, Env, Local};
44

5+
use nodejs_sys as napi;
6+
57
#[repr(C)]
68
pub struct CCallback {
79
pub static_callback: *mut c_void,
@@ -17,19 +19,78 @@ impl Default for CCallback {
1719
}
1820
}
1921

20-
pub unsafe extern "C" fn set_return(_info: &FunctionCallbackInfo, _value: Local) { unimplemented!() }
22+
pub unsafe extern "C" fn set_return(_info: FunctionCallbackInfo, _value: Local) {
23+
24+
}
2125

22-
pub unsafe extern "C" fn get_isolate(_info: &FunctionCallbackInfo) -> Env { unimplemented!() }
26+
pub unsafe extern "C" fn get_isolate(info: FunctionCallbackInfo) -> Env { unimplemented!() }
2327

2428
// FIXME: Remove. This will never be implemented
2529
pub unsafe extern "C" fn current_isolate() -> Env { panic!("current_isolate won't be implemented in n-api") }
2630

27-
pub unsafe extern "C" fn is_construct(_info: &FunctionCallbackInfo) -> bool { unimplemented!() }
31+
pub unsafe extern "C" fn is_construct(_info: FunctionCallbackInfo) -> bool { unimplemented!() }
2832

29-
pub unsafe extern "C" fn this(_info: &FunctionCallbackInfo, _out: &mut Local) { unimplemented!() }
33+
pub unsafe extern "C" fn this(env: Env, info: FunctionCallbackInfo, out: &mut Local) {
34+
let status = napi::napi_get_cb_info(
35+
env,
36+
info,
37+
null_mut(),
38+
null_mut(),
39+
out as *mut _,
40+
null_mut(),
41+
);
42+
assert_eq!(status, napi::napi_status::napi_ok);
43+
}
3044

31-
pub unsafe extern "C" fn data(_info: &FunctionCallbackInfo, _out: &mut Local) { unimplemented!() }
45+
/// Mutates the `out` argument provided to refer to the associated data value of the
46+
/// `napi_callback_info`.
47+
pub unsafe extern "C" fn data(env: Env, info: FunctionCallbackInfo, out: &mut *mut c_void) {
48+
let mut data = null_mut();
49+
let status = napi::napi_get_cb_info(
50+
env,
51+
info,
52+
null_mut(),
53+
null_mut(),
54+
null_mut(),
55+
&mut data as *mut _,
56+
);
57+
if status == napi::napi_status::napi_ok {
58+
*out = data;
59+
}
60+
}
61+
62+
/// Gets the number of arguments passed to the function.
63+
pub unsafe extern "C" fn len(env: Env, info: FunctionCallbackInfo) -> i32 {
64+
let mut argc = 0usize;
65+
let status = napi::napi_get_cb_info(
66+
env,
67+
info,
68+
&mut argc as *mut _,
69+
null_mut(),
70+
null_mut(),
71+
null_mut(),
72+
);
73+
assert_eq!(status, napi::napi_status::napi_ok);
74+
argc as i32
75+
}
3276

33-
pub unsafe extern "C" fn len(_info: &FunctionCallbackInfo) -> i32 { unimplemented!() }
77+
/// Mutates the `out` argument provided to refer to the `napi_value` of the `i`th argument
78+
/// passed to the function.
79+
pub unsafe extern "C" fn get(env: Env, info: FunctionCallbackInfo, i: i32, out: &mut Local) {
80+
// TODO make this not allocate: https://github.com/neon-bindings/neon/issues/530
81+
// Instead, we can probably get all the arguments at once in `neon` itself?
82+
let mut args = vec![null_mut(); (i + 1) as usize];
83+
let mut num_args = args.len();
3484

35-
pub unsafe extern "C" fn get(_info: &FunctionCallbackInfo, _i: i32, _out: &mut Local) { unimplemented!() }
85+
let status = napi::napi_get_cb_info(
86+
env,
87+
info,
88+
&mut num_args as *mut _,
89+
args.as_mut_ptr(),
90+
null_mut(),
91+
null_mut(),
92+
);
93+
assert_eq!(status, napi::napi_status::napi_ok);
94+
assert!(num_args > i as usize);
95+
*out = args[i as usize];
96+
}

crates/neon-runtime/src/napi/class.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ pub unsafe extern "C" fn metadata_to_constructor(_out: &mut Local, _isolate: Env
2626

2727
// FIXME: get rid of all the "kernel" nomenclature
2828

29-
pub unsafe extern "C" fn get_allocate_kernel(_obj: Local) -> *mut c_void { unimplemented!() }
29+
pub unsafe extern "C" fn get_allocate_kernel(_data: *mut c_void) -> *mut c_void { unimplemented!() }
3030

31-
pub unsafe extern "C" fn get_construct_kernel(_obj: Local) -> *mut c_void { unimplemented!() }
31+
pub unsafe extern "C" fn get_construct_kernel(_data: *mut c_void) -> *mut c_void { unimplemented!() }
3232

33-
pub unsafe extern "C" fn get_call_kernel(_obj: Local) -> *mut c_void { unimplemented!() }
33+
pub unsafe extern "C" fn get_call_kernel(_data: *mut c_void) -> *mut c_void { unimplemented!() }
3434

3535
pub unsafe extern "C" fn constructor(_out: &mut Local, _ft: Local) -> bool { unimplemented!() }
3636

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,44 @@
1-
use std::os::raw::c_void;
1+
//! Facilities for working with JS functions.
2+
23
use call::CCallback;
34
use raw::{Env, Local};
5+
use std::os::raw::c_void;
6+
use std::mem::MaybeUninit;
7+
use std::ptr::{null, null_mut};
8+
9+
use nodejs_sys as napi;
10+
11+
/// Mutates the `out` argument provided to refer to a newly created `v8::Function`. Returns
12+
/// `false` if the value couldn't be created.
13+
pub unsafe extern "C" fn new(out: &mut Local, env: Env, callback: CCallback) -> bool {
14+
let status = napi::napi_create_function(
15+
env,
16+
null(),
17+
0,
18+
Some(std::mem::transmute(callback.static_callback)),
19+
callback.dynamic_callback,
20+
out as *mut Local,
21+
);
22+
23+
status == napi::napi_status::napi_ok
24+
}
25+
26+
pub unsafe extern "C" fn new_template(_out: &mut Local, _env: Env, _callback: CCallback) -> bool {
27+
unimplemented!()
28+
}
429

5-
pub unsafe extern "C" fn new(_out: &mut Local, _env: Env, _callback: CCallback) -> bool { unimplemented!() }
30+
pub unsafe extern "C" fn get_dynamic_callback(env: Env, data: *mut c_void) -> *mut c_void {
31+
data
32+
}
633

7-
pub unsafe extern "C" fn new_template(_out: &mut Local, _env: Env, _callback: CCallback) -> bool { unimplemented!() }
34+
pub unsafe extern "C" fn call(out: &mut Local, env: Env, fun: Local, this: Local, argc: i32, argv: *mut c_void) -> bool {
35+
let status = napi::napi_call_function(env, this, fun, argc as usize, argv as *const _, out as *mut _);
836

9-
pub unsafe extern "C" fn get_dynamic_callback(_obj: Local) -> *mut c_void { unimplemented!() }
37+
status == napi::napi_status::napi_ok
38+
}
1039

11-
pub unsafe extern "C" fn call(_out: &mut Local, _env: Env, _fun: Local, _this: Local, _argc: i32, _argv: *mut c_void) -> bool { unimplemented!() }
40+
pub unsafe extern "C" fn construct(out: &mut Local, env: Env, fun: Local, argc: i32, argv: *mut c_void) -> bool {
41+
let status = napi::napi_new_instance(env, fun, argc as usize, argv as *const _, out as *mut _);
1242

13-
pub unsafe extern "C" fn construct(_out: &mut Local, _env: Env, _fun: Local, _argc: i32, _argv: *mut c_void) -> bool { unimplemented!() }
43+
status == napi::napi_status::napi_ok
44+
}

crates/neon-runtime/src/napi/raw.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use std::ptr;
33

44
use nodejs_sys as napi;
55

6-
pub type Local = napi::napi_value;
6+
pub type Local = napi::napi_value;
77

8-
pub type FunctionCallbackInfo = c_void;
8+
pub type FunctionCallbackInfo = napi::napi_callback_info;
99

1010
pub type Env = napi::napi_env;
1111

crates/neon-runtime/src/napi/scope.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,6 @@ pub unsafe extern "C" fn escapable_size() -> usize { unimplemented!() }
6969

7070
pub unsafe extern "C" fn escapable_alignment() -> usize { unimplemented!() }
7171

72-
pub unsafe extern "C" fn get_global(_env: Env, _out: &mut Local) { unimplemented!() }
72+
pub unsafe extern "C" fn get_global(env: Env, out: &mut Local) {
73+
assert_eq!(napi::napi_get_global(env, out as *mut _), napi::napi_status::napi_ok);
74+
}

crates/neon-runtime/src/napi/tag.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,15 @@ pub unsafe extern "C" fn is_string(env: Env, val: Local) -> bool {
3131
is_type(env, val, napi::napi_valuetype::napi_string)
3232
}
3333

34-
pub unsafe extern "C" fn is_object(_env: Env, _val: Local) -> bool { unimplemented!() }
34+
pub unsafe extern "C" fn is_object(env: Env, val: Local) -> bool {
35+
is_type(env, val, napi::napi_valuetype::napi_object)
36+
}
3537

3638
pub unsafe extern "C" fn is_array(_env: Env, _val: Local) -> bool { unimplemented!() }
3739

38-
pub unsafe extern "C" fn is_function(_env: Env, _val: Local) -> bool { unimplemented!() }
40+
pub unsafe extern "C" fn is_function(env: Env, val: Local) -> bool {
41+
is_type(env, val, napi::napi_valuetype::napi_function)
42+
}
3943

4044
pub unsafe extern "C" fn is_error(_env: Env, _val: Local) -> bool { unimplemented!() }
4145

crates/neon-sys/native/src/neon.cc

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,30 @@ extern "C" bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo<v8::Value> *info)
2626
return info->IsConstructCall();
2727
}
2828

29-
extern "C" void Neon_Call_This(v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Object> *out) {
29+
extern "C" void Neon_Call_This(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Object> *out) {
3030
*out = info->This();
3131
}
3232

33-
extern "C" void Neon_Call_Data(v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Value> *out) {
33+
extern "C" void Neon_Call_Data(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, void **out) {
3434
/*
3535
printf("Call_Data: v8 info = %p\n", *(void **)info);
3636
dump((void *)info, 3);
3737
printf("Call_Data: v8 info implicit:\n");
3838
dump_implicit((void *)info);
3939
*/
40-
*out = info->Data();
40+
41+
// Call data is stored wrapped in a v8::External by Neon_Fun_New et al, so we need to unwrap it before handing it back to Rust.
42+
v8::Local<v8::Value> external = info->Data();
43+
if (external->IsExternal()) {
44+
*out = external.As<v8::External>()->Value();
45+
}
4146
}
4247

43-
extern "C" int32_t Neon_Call_Length(v8::FunctionCallbackInfo<v8::Value> *info) {
48+
extern "C" int32_t Neon_Call_Length(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info) {
4449
return info->Length();
4550
}
4651

47-
extern "C" void Neon_Call_Get(v8::FunctionCallbackInfo<v8::Value> *info, int32_t i, v8::Local<v8::Value> *out) {
52+
extern "C" void Neon_Call_Get(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, int32_t i, v8::Local<v8::Value> *out) {
4853
*out = (*info)[i];
4954
}
5055

@@ -330,18 +335,18 @@ extern "C" void Neon_Class_SetClassMap(v8::Isolate *isolate, void *map, Neon_Dro
330335
node::AtExit(cleanup_class_map, holder);
331336
}
332337

333-
extern "C" void *Neon_Class_GetCallKernel(v8::Local<v8::External> wrapper) {
334-
neon::ClassMetadata *metadata = static_cast<neon::ClassMetadata *>(wrapper->Value());
338+
extern "C" void *Neon_Class_GetCallKernel(void *wrapper) {
339+
neon::ClassMetadata *metadata = static_cast<neon::ClassMetadata *>(wrapper);
335340
return metadata->GetCallKernel();
336341
}
337342

338-
extern "C" void *Neon_Class_GetConstructKernel(v8::Local<v8::External> wrapper) {
339-
neon::ClassMetadata *metadata = static_cast<neon::ClassMetadata *>(wrapper->Value());
343+
extern "C" void *Neon_Class_GetConstructKernel(void *wrapper) {
344+
neon::ClassMetadata *metadata = static_cast<neon::ClassMetadata *>(wrapper);
340345
return metadata->GetConstructKernel();
341346
}
342347

343-
extern "C" void *Neon_Class_GetAllocateKernel(v8::Local<v8::External> wrapper) {
344-
neon::BaseClassMetadata *metadata = static_cast<neon::BaseClassMetadata *>(wrapper->Value());
348+
extern "C" void *Neon_Class_GetAllocateKernel(void *wrapper) {
349+
neon::BaseClassMetadata *metadata = static_cast<neon::BaseClassMetadata *>(wrapper);
345350
return metadata->GetAllocateKernel();
346351
}
347352

@@ -433,8 +438,8 @@ extern "C" bool Neon_Fun_New(v8::Local<v8::Function> *out, v8::Isolate *isolate,
433438
return maybe_result.ToLocal(out);
434439
}
435440

436-
extern "C" void *Neon_Fun_GetDynamicCallback(v8::Local<v8::External> data) {
437-
return data->Value();
441+
extern "C" void *Neon_Fun_GetDynamicCallback(v8::Isolate *isolate, void *data) {
442+
return data;
438443
}
439444

440445
extern "C" bool Neon_Fun_Call(v8::Local<v8::Value> *out, v8::Isolate *isolate, v8::Local<v8::Function> fun, v8::Local<v8::Value> self, int32_t argc, v8::Local<v8::Value> argv[]) {

crates/neon-sys/native/src/neon.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ extern "C" {
1717
void *Neon_Call_GetIsolate(v8::FunctionCallbackInfo<v8::Value> *info);
1818
void *Neon_Call_CurrentIsolate();
1919
bool Neon_Call_IsConstruct(v8::FunctionCallbackInfo<v8::Value> *info);
20-
void Neon_Call_This(v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Object> *out);
21-
void Neon_Call_Data(v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Value> *out);
22-
int32_t Neon_Call_Length(v8::FunctionCallbackInfo<v8::Value> *info);
23-
void Neon_Call_Get(v8::FunctionCallbackInfo<v8::Value> *info, int32_t i, v8::Local<v8::Value> *out);
20+
void Neon_Call_This(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, v8::Local<v8::Object> *out);
21+
void Neon_Call_Data(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, void **out);
22+
int32_t Neon_Call_Length(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info);
23+
void Neon_Call_Get(v8::Isolate *isolate, v8::FunctionCallbackInfo<v8::Value> *info, int32_t i, v8::Local<v8::Value> *out);
2424

2525
void Neon_Primitive_Number(v8::Local<v8::Number> *out, v8::Isolate *isolate, double value);
2626
void Neon_Primitive_Undefined(v8::Local<v8::Primitive> *out, v8::Isolate *isolate);
@@ -75,7 +75,7 @@ extern "C" {
7575

7676
bool Neon_Fun_New(v8::Local<v8::Function> *out, v8::Isolate *isolate, callback_t callback);
7777
bool Neon_Fun_Template_New(v8::Local<v8::FunctionTemplate> *out, v8::Isolate *isolate, callback_t callback);
78-
void *Neon_Fun_GetDynamicCallback(v8::Local<v8::External> obj);
78+
void *Neon_Fun_GetDynamicCallback(v8::Isolate *isolate, void *obj);
7979
bool Neon_Fun_Call(v8::Local<v8::Value> *out, v8::Isolate *isolate, v8::Local<v8::Function> fun, v8::Local<v8::Value> self, int32_t argc, v8::Local<v8::Value> argv[]);
8080
bool Neon_Fun_Construct(v8::Local<v8::Object> *out, v8::Isolate *isolate, v8::Local<v8::Function> fun, int32_t argc, v8::Local<v8::Value> argv[]);
8181

@@ -95,9 +95,9 @@ extern "C" {
9595
callback_t call,
9696
Neon_DropCallback drop);
9797
// FIXME: get rid of all the "kernel" nomenclature
98-
void *Neon_Class_GetCallKernel(v8::Local<v8::External> wrapper);
99-
void *Neon_Class_GetConstructKernel(v8::Local<v8::External> wrapper);
100-
void *Neon_Class_GetAllocateKernel(v8::Local<v8::External> wrapper);
98+
void *Neon_Class_GetCallKernel(void *wrapper);
99+
void *Neon_Class_GetConstructKernel(void *wrapper);
100+
void *Neon_Class_GetAllocateKernel(void *wrapper);
101101
bool Neon_Class_Constructor(v8::Local<v8::Function> *out, v8::Local<v8::FunctionTemplate> ft);
102102
bool Neon_Class_HasInstance(void *metadata, v8::Local<v8::Value> v);
103103
bool Neon_Class_SetName(v8::Isolate *isolate, void *metadata, const char *name, uint32_t byte_length);

crates/neon-sys/src/lib.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub struct Local {
1616
///
1717
/// It contains the arguments used to invoke the function, the isolate reference, the `this` object
1818
/// the function is bound to and a mechanism to return a value to the caller.
19-
pub type FunctionCallbackInfo = c_void;
19+
pub type FunctionCallbackInfo = *const c_void;
2020

2121
#[repr(C)]
2222
#[derive(Debug, Copy, Clone)]
@@ -93,14 +93,14 @@ extern "C" {
9393
pub fn Neon_Buffer_Uninitialized(out: &mut Local, size: u32) -> bool;
9494
pub fn Neon_Buffer_Data<'a, 'b>(base_out: &'a mut *mut c_void, obj: Local) -> usize;
9595

96-
pub fn Neon_Call_SetReturn(info: &FunctionCallbackInfo, value: Local);
97-
pub fn Neon_Call_GetIsolate(info: &FunctionCallbackInfo) -> Isolate;
96+
pub fn Neon_Call_SetReturn(info: FunctionCallbackInfo, value: Local);
97+
pub fn Neon_Call_GetIsolate(info: FunctionCallbackInfo) -> Isolate;
9898
pub fn Neon_Call_CurrentIsolate() -> Isolate;
99-
pub fn Neon_Call_IsConstruct(info: &FunctionCallbackInfo) -> bool;
100-
pub fn Neon_Call_This(info: &FunctionCallbackInfo, out: &mut Local);
101-
pub fn Neon_Call_Data(info: &FunctionCallbackInfo, out: &mut Local);
102-
pub fn Neon_Call_Length(info: &FunctionCallbackInfo) -> i32;
103-
pub fn Neon_Call_Get(info: &FunctionCallbackInfo, i: i32, out: &mut Local);
99+
pub fn Neon_Call_IsConstruct(info: FunctionCallbackInfo) -> bool;
100+
pub fn Neon_Call_This(isolate: Isolate, info: FunctionCallbackInfo, out: &mut Local);
101+
pub fn Neon_Call_Data(isolate: Isolate, info: FunctionCallbackInfo, out: &mut *mut c_void);
102+
pub fn Neon_Call_Length(isolate: Isolate, info: FunctionCallbackInfo) -> i32;
103+
pub fn Neon_Call_Get(isolate: Isolate, info: FunctionCallbackInfo, i: i32, out: &mut Local);
104104

105105
pub fn Neon_Class_GetClassMap(isolate: Isolate) -> *mut c_void;
106106
pub fn Neon_Class_SetClassMap(isolate: Isolate, map: *mut c_void, free_map: *mut c_void);
@@ -115,9 +115,9 @@ extern "C" {
115115
pub fn Neon_Class_ThrowThisError(isolate: Isolate, metadata: *mut c_void);
116116
pub fn Neon_Class_AddMethod(isolate: Isolate, metadata: *mut c_void, name: *const u8, byte_length: u32, method: Local) -> bool;
117117
pub fn Neon_Class_MetadataToConstructor(out: &mut Local, isolate: Isolate, metadata: *mut c_void) -> bool;
118-
pub fn Neon_Class_GetAllocateKernel(obj: Local) -> *mut c_void;
119-
pub fn Neon_Class_GetConstructKernel(obj: Local) -> *mut c_void;
120-
pub fn Neon_Class_GetCallKernel(obj: Local) -> *mut c_void;
118+
pub fn Neon_Class_GetAllocateKernel(data: *mut c_void) -> *mut c_void;
119+
pub fn Neon_Class_GetConstructKernel(data: *mut c_void) -> *mut c_void;
120+
pub fn Neon_Class_GetCallKernel(data: *mut c_void) -> *mut c_void;
121121
pub fn Neon_Class_Constructor(out: &mut Local, ft: Local) -> bool;
122122
pub fn Neon_Class_HasInstance(metadata: *mut c_void, v: Local) -> bool;
123123
pub fn Neon_Class_GetInstanceInternals(obj: Local) -> *mut c_void;
@@ -133,7 +133,7 @@ extern "C" {
133133

134134
pub fn Neon_Fun_New(out: &mut Local, isolate: Isolate, callback: CCallback) -> bool;
135135
pub fn Neon_Fun_Template_New(out: &mut Local, isolate: Isolate, callback: CCallback) -> bool;
136-
pub fn Neon_Fun_GetDynamicCallback(obj: Local) -> *mut c_void;
136+
pub fn Neon_Fun_GetDynamicCallback(isolate: Isolate, data: *mut c_void) -> *mut c_void;
137137
pub fn Neon_Fun_Call(out: &mut Local, isolate: Isolate, fun: Local, this: Local, argc: i32, argv: *mut c_void) -> bool;
138138
pub fn Neon_Fun_Construct(out: &mut Local, isolate: Isolate, fun: Local, argc: i32, argv: *mut c_void) -> bool;
139139

0 commit comments

Comments
 (0)