koffi 2.3.21-beta.2 → 2.3.21-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/2.3.21-beta.3/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.3/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.21-beta.3/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.3/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.21-beta.3/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.21-beta.3/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.3/koffi_linux_ia32/koffi.node +0 -0
- package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.21-beta.3/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.21-beta.3/koffi_win32_arm64/koffi.node +0 -0
- package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_win32_ia32/koffi.node +0 -0
- package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_win32_x64/koffi.node +0 -0
- package/package.json +1 -1
- package/src/index.d.ts +6 -2
- package/src/index.js +2 -1
- package/src/koffi/src/abi_arm32.cc +3 -3
- package/src/koffi/src/abi_arm64.cc +3 -3
- package/src/koffi/src/abi_riscv64.cc +3 -3
- package/src/koffi/src/abi_x64_sysv.cc +3 -3
- package/src/koffi/src/abi_x64_win.cc +3 -3
- package/src/koffi/src/abi_x86.cc +3 -3
- package/src/koffi/src/call.hh +1 -1
- package/src/koffi/src/ffi.cc +150 -46
- package/src/koffi/src/ffi.hh +2 -1
- package/src/koffi/src/parser.cc +2 -0
- package/build/2.3.21-beta.2/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_win32_arm64/koffi.node +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_win32_arm64/koffi.exp +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_win32_arm64/koffi.lib +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_win32_ia32/koffi.exp +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_win32_ia32/koffi.lib +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_win32_x64/koffi.exp +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.3}/koffi_win32_x64/koffi.lib +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -93,6 +93,8 @@ declare module 'koffi' {
|
|
|
93
93
|
|
|
94
94
|
export function opaque(name: string): IKoffiCType;
|
|
95
95
|
export function opaque(): IKoffiCType;
|
|
96
|
+
/** @deprecated */ export function handle(name: string): IKoffiCType;
|
|
97
|
+
/** @deprecated */ export function handle(): IKoffiCType;
|
|
96
98
|
|
|
97
99
|
export function pointer(value: TypeSpec): IKoffiCType;
|
|
98
100
|
export function pointer(value: TypeSpec, asteriskCount: number): IKoffiCType;
|
|
@@ -105,8 +107,10 @@ declare module 'koffi' {
|
|
|
105
107
|
export function disposable(name: string, type: TypeSpec): IKoffiCType;
|
|
106
108
|
export function disposable(name: string, type: TypeSpec, freeFunction: Function): IKoffiCType;
|
|
107
109
|
|
|
108
|
-
export function
|
|
109
|
-
export function
|
|
110
|
+
export function proto(definition: string): IKoffiCType;
|
|
111
|
+
export function proto(name: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
112
|
+
/** @deprecated */ export function callback(definition: string): IKoffiCType;
|
|
113
|
+
/** @deprecated */ export function callback(name: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
110
114
|
|
|
111
115
|
export function register(callback: Function, type: TypeSpec): IKoffiRegisteredCallback;
|
|
112
116
|
export function register(thisValue: any, callback: Function, type: TypeSpec): IKoffiRegisteredCallback;
|
package/src/index.js
CHANGED
|
@@ -57,5 +57,6 @@ module.exports = {
|
|
|
57
57
|
...native,
|
|
58
58
|
|
|
59
59
|
// Deprecated functions
|
|
60
|
-
handle: util.deprecate(native.opaque, 'The koffi.handle() function was deprecated in Koffi 2.1, use koffi.opaque() instead', 'KOFFI001')
|
|
60
|
+
handle: util.deprecate(native.opaque, 'The koffi.handle() function was deprecated in Koffi 2.1, use koffi.opaque() instead', 'KOFFI001'),
|
|
61
|
+
callback: util.deprecate(native.proto, 'The koffi.callback() function was deprecated in Koffi 2.4, use koffi.proto() instead', 'KOFFI002')
|
|
61
62
|
};
|
|
@@ -456,12 +456,12 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
456
456
|
return true;
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
459
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
460
460
|
{
|
|
461
461
|
#define PERFORM_CALL(Suffix) \
|
|
462
462
|
([&]() { \
|
|
463
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(
|
|
464
|
-
: ForwardCall ## Suffix(
|
|
463
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(native, new_sp, &old_sp) \
|
|
464
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
465
465
|
return ret; \
|
|
466
466
|
})()
|
|
467
467
|
|
|
@@ -561,7 +561,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
561
561
|
return true;
|
|
562
562
|
}
|
|
563
563
|
|
|
564
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
564
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
565
565
|
{
|
|
566
566
|
#ifdef _WIN32
|
|
567
567
|
TEB *teb = GetTEB();
|
|
@@ -589,8 +589,8 @@ void CallData::Execute(const FunctionInfo *func)
|
|
|
589
589
|
|
|
590
590
|
#define PERFORM_CALL(Suffix) \
|
|
591
591
|
([&]() { \
|
|
592
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(
|
|
593
|
-
: ForwardCall ## Suffix(
|
|
592
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(native, new_sp, &old_sp) \
|
|
593
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
594
594
|
return ret; \
|
|
595
595
|
})()
|
|
596
596
|
|
|
@@ -386,12 +386,12 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
386
386
|
return true;
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
389
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
390
390
|
{
|
|
391
391
|
#define PERFORM_CALL(Suffix) \
|
|
392
392
|
([&]() { \
|
|
393
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(
|
|
394
|
-
: ForwardCall ## Suffix(
|
|
393
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(native, new_sp, &old_sp) \
|
|
394
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
395
395
|
return ret; \
|
|
396
396
|
})()
|
|
397
397
|
|
|
@@ -425,12 +425,12 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
425
425
|
return true;
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
428
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
429
429
|
{
|
|
430
430
|
#define PERFORM_CALL(Suffix) \
|
|
431
431
|
([&]() { \
|
|
432
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(
|
|
433
|
-
: ForwardCall ## Suffix(
|
|
432
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(native, new_sp, &old_sp) \
|
|
433
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
434
434
|
return ret; \
|
|
435
435
|
})()
|
|
436
436
|
|
|
@@ -224,7 +224,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
224
224
|
return true;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
227
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
228
228
|
{
|
|
229
229
|
TEB *teb = GetTEB();
|
|
230
230
|
|
|
@@ -250,8 +250,8 @@ void CallData::Execute(const FunctionInfo *func)
|
|
|
250
250
|
|
|
251
251
|
#define PERFORM_CALL(Suffix) \
|
|
252
252
|
([&]() { \
|
|
253
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(
|
|
254
|
-
: ForwardCall ## Suffix(
|
|
253
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(native, new_sp, &old_sp) \
|
|
254
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
255
255
|
return ret; \
|
|
256
256
|
})()
|
|
257
257
|
|
package/src/koffi/src/abi_x86.cc
CHANGED
|
@@ -308,7 +308,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
308
308
|
return true;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
311
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
312
312
|
{
|
|
313
313
|
#ifdef _WIN32
|
|
314
314
|
TEB *teb = GetTEB();
|
|
@@ -336,8 +336,8 @@ void CallData::Execute(const FunctionInfo *func)
|
|
|
336
336
|
|
|
337
337
|
#define PERFORM_CALL(Suffix) \
|
|
338
338
|
([&]() { \
|
|
339
|
-
auto ret = (func->fast ? ForwardCallR ## Suffix(
|
|
340
|
-
: ForwardCall ## Suffix(
|
|
339
|
+
auto ret = (func->fast ? ForwardCallR ## Suffix(native, new_sp, &old_sp) \
|
|
340
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
341
341
|
return ret; \
|
|
342
342
|
})()
|
|
343
343
|
|
package/src/koffi/src/call.hh
CHANGED
|
@@ -102,7 +102,7 @@ public:
|
|
|
102
102
|
#endif
|
|
103
103
|
|
|
104
104
|
INLINE_IF_UNITY bool Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info);
|
|
105
|
-
INLINE_IF_UNITY void Execute(const FunctionInfo *func);
|
|
105
|
+
INLINE_IF_UNITY void Execute(const FunctionInfo *func, void *native);
|
|
106
106
|
INLINE_IF_UNITY Napi::Value Complete(const FunctionInfo *func);
|
|
107
107
|
|
|
108
108
|
#undef INLINE_IF_UNITY
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -275,7 +275,7 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
|
|
|
275
275
|
value = array[1u];
|
|
276
276
|
align = (int16_t)align64;
|
|
277
277
|
}
|
|
278
|
-
|
|
278
|
+
|
|
279
279
|
member.type = ResolveType(value);
|
|
280
280
|
if (!member.type)
|
|
281
281
|
return env.Null();
|
|
@@ -403,7 +403,7 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
|
|
|
403
403
|
value = array[1u];
|
|
404
404
|
align = (int16_t)align64;
|
|
405
405
|
}
|
|
406
|
-
|
|
406
|
+
|
|
407
407
|
member.type = ResolveType(value);
|
|
408
408
|
if (!member.type)
|
|
409
409
|
return env.Null();
|
|
@@ -920,10 +920,12 @@ static bool ParseClassicFunction(Napi::Env env, Napi::String name, Napi::Value r
|
|
|
920
920
|
func->parameters.Append(param);
|
|
921
921
|
}
|
|
922
922
|
|
|
923
|
+
func->required_parameters = (int8_t)func->parameters.len;
|
|
924
|
+
|
|
923
925
|
return true;
|
|
924
926
|
}
|
|
925
927
|
|
|
926
|
-
static Napi::Value
|
|
928
|
+
static Napi::Value CreateFunctionType(const Napi::CallbackInfo &info)
|
|
927
929
|
{
|
|
928
930
|
Napi::Env env = info.Env();
|
|
929
931
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
@@ -956,6 +958,12 @@ static Napi::Value CreateCallbackType(const Napi::CallbackInfo &info)
|
|
|
956
958
|
if (!AnalyseFunction(env, instance, func))
|
|
957
959
|
return env.Null();
|
|
958
960
|
|
|
961
|
+
// Adjust parameter offsets for koffi.call()
|
|
962
|
+
for (ParameterInfo ¶m: func->parameters) {
|
|
963
|
+
param.offset += 2;
|
|
964
|
+
}
|
|
965
|
+
func->required_parameters += 2;
|
|
966
|
+
|
|
959
967
|
// We cannot fail after this check
|
|
960
968
|
if (instance->types_map.Find(func->name)) {
|
|
961
969
|
ThrowError<Napi::Error>(env, "Duplicate type name '%1'", func->name);
|
|
@@ -1239,13 +1247,13 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
|
|
|
1239
1247
|
return mem;
|
|
1240
1248
|
}
|
|
1241
1249
|
|
|
1242
|
-
static Napi::Value TranslateNormalCall(const
|
|
1250
|
+
static Napi::Value TranslateNormalCall(const FunctionInfo *func, void *native,
|
|
1251
|
+
const Napi::CallbackInfo &info)
|
|
1243
1252
|
{
|
|
1244
1253
|
Napi::Env env = info.Env();
|
|
1245
1254
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1246
|
-
FunctionInfo *func = (FunctionInfo *)info.Data();
|
|
1247
1255
|
|
|
1248
|
-
if (RG_UNLIKELY(info.Length() < (uint32_t)func->
|
|
1256
|
+
if (RG_UNLIKELY(info.Length() < (uint32_t)func->required_parameters)) {
|
|
1249
1257
|
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
|
|
1250
1258
|
return env.Null();
|
|
1251
1259
|
}
|
|
@@ -1265,37 +1273,44 @@ static Napi::Value TranslateNormalCall(const Napi::CallbackInfo &info)
|
|
|
1265
1273
|
RG_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1266
1274
|
exec_call = &call;
|
|
1267
1275
|
|
|
1268
|
-
call.Execute(func);
|
|
1276
|
+
call.Execute(func, native);
|
|
1269
1277
|
}
|
|
1270
1278
|
|
|
1271
1279
|
return call.Complete(func);
|
|
1272
1280
|
}
|
|
1273
1281
|
|
|
1274
|
-
static Napi::Value
|
|
1282
|
+
static Napi::Value TranslateNormalCall(const Napi::CallbackInfo &info)
|
|
1283
|
+
{
|
|
1284
|
+
FunctionInfo *func = (FunctionInfo *)info.Data();
|
|
1285
|
+
return TranslateNormalCall(func, func->native, info);
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
static Napi::Value TranslateVariadicCall(const FunctionInfo *func, void *native,
|
|
1289
|
+
const Napi::CallbackInfo &info)
|
|
1275
1290
|
{
|
|
1276
1291
|
Napi::Env env = info.Env();
|
|
1277
1292
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1278
1293
|
|
|
1279
|
-
FunctionInfo
|
|
1280
|
-
memcpy((void *)&
|
|
1281
|
-
|
|
1294
|
+
FunctionInfo copy;
|
|
1295
|
+
memcpy((void *)©, func, RG_SIZE(*func));
|
|
1296
|
+
copy.lib = nullptr;
|
|
1282
1297
|
|
|
1283
1298
|
// This makes variadic calls non-reentrant
|
|
1284
|
-
RG_DEFER_C(len =
|
|
1285
|
-
|
|
1286
|
-
|
|
1299
|
+
RG_DEFER_C(len = copy.parameters.len) {
|
|
1300
|
+
copy.parameters.RemoveFrom(len);
|
|
1301
|
+
copy.parameters.Leak();
|
|
1287
1302
|
};
|
|
1288
1303
|
|
|
1289
|
-
if (RG_UNLIKELY(info.Length() < (uint32_t)
|
|
1290
|
-
ThrowError<Napi::TypeError>(env, "Expected %1 arguments or more, got %2",
|
|
1304
|
+
if (RG_UNLIKELY(info.Length() < (uint32_t)copy.required_parameters)) {
|
|
1305
|
+
ThrowError<Napi::TypeError>(env, "Expected %1 arguments or more, got %2", copy.parameters.len, info.Length());
|
|
1291
1306
|
return env.Null();
|
|
1292
1307
|
}
|
|
1293
|
-
if (RG_UNLIKELY((info.Length() -
|
|
1308
|
+
if (RG_UNLIKELY((info.Length() - copy.required_parameters) % 2)) {
|
|
1294
1309
|
ThrowError<Napi::Error>(env, "Missing value argument for variadic call");
|
|
1295
1310
|
return env.Null();
|
|
1296
1311
|
}
|
|
1297
1312
|
|
|
1298
|
-
for (Size i =
|
|
1313
|
+
for (Size i = copy.required_parameters; i < (Size)info.Length(); i += 2) {
|
|
1299
1314
|
ParameterInfo param = {};
|
|
1300
1315
|
|
|
1301
1316
|
param.type = ResolveType(info[(uint32_t)i], ¶m.directions);
|
|
@@ -1306,11 +1321,11 @@ static Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
|
1306
1321
|
ThrowError<Napi::TypeError>(env, "Type %1 cannot be used as a parameter (maybe try %1 *)", param.type->name);
|
|
1307
1322
|
return env.Null();
|
|
1308
1323
|
}
|
|
1309
|
-
if (RG_UNLIKELY(
|
|
1324
|
+
if (RG_UNLIKELY(copy.parameters.len >= MaxParameters)) {
|
|
1310
1325
|
ThrowError<Napi::TypeError>(env, "Functions cannot have more than %1 parameters", MaxParameters);
|
|
1311
1326
|
return env.Null();
|
|
1312
1327
|
}
|
|
1313
|
-
if (RG_UNLIKELY((param.directions & 2) && ++
|
|
1328
|
+
if (RG_UNLIKELY((param.directions & 2) && ++copy.out_parameters >= MaxOutParameters)) {
|
|
1314
1329
|
ThrowError<Napi::TypeError>(env, "Functions cannot have more than %1 output parameters", MaxOutParameters);
|
|
1315
1330
|
return env.Null();
|
|
1316
1331
|
}
|
|
@@ -1318,20 +1333,20 @@ static Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
|
1318
1333
|
param.variadic = true;
|
|
1319
1334
|
param.offset = (int8_t)(i + 1);
|
|
1320
1335
|
|
|
1321
|
-
|
|
1336
|
+
copy.parameters.Append(param);
|
|
1322
1337
|
}
|
|
1323
1338
|
|
|
1324
|
-
if (RG_UNLIKELY(!AnalyseFunction(env, instance, &
|
|
1339
|
+
if (RG_UNLIKELY(!AnalyseFunction(env, instance, ©)))
|
|
1325
1340
|
return env.Null();
|
|
1326
1341
|
|
|
1327
1342
|
InstanceMemory *mem = instance->memories[0];
|
|
1328
1343
|
CallData call(env, instance, mem);
|
|
1329
1344
|
|
|
1330
|
-
if (!RG_UNLIKELY(call.Prepare(&
|
|
1345
|
+
if (!RG_UNLIKELY(call.Prepare(©, info)))
|
|
1331
1346
|
return env.Null();
|
|
1332
1347
|
|
|
1333
1348
|
if (instance->debug) {
|
|
1334
|
-
call.DumpForward(&
|
|
1349
|
+
call.DumpForward(©);
|
|
1335
1350
|
}
|
|
1336
1351
|
|
|
1337
1352
|
// Execute call
|
|
@@ -1339,23 +1354,31 @@ static Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
|
1339
1354
|
RG_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1340
1355
|
exec_call = &call;
|
|
1341
1356
|
|
|
1342
|
-
call.Execute(&
|
|
1357
|
+
call.Execute(©, native);
|
|
1343
1358
|
}
|
|
1344
1359
|
|
|
1345
|
-
return call.Complete(&
|
|
1360
|
+
return call.Complete(©);
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
static Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
1364
|
+
{
|
|
1365
|
+
FunctionInfo *func = (FunctionInfo *)info.Data();
|
|
1366
|
+
return TranslateVariadicCall(func, func->native, info);
|
|
1346
1367
|
}
|
|
1347
1368
|
|
|
1348
1369
|
class AsyncCall: public Napi::AsyncWorker {
|
|
1349
1370
|
Napi::Env env;
|
|
1371
|
+
|
|
1350
1372
|
const FunctionInfo *func;
|
|
1373
|
+
void *native;
|
|
1351
1374
|
|
|
1352
1375
|
CallData call;
|
|
1353
1376
|
bool prepared = false;
|
|
1354
1377
|
|
|
1355
1378
|
public:
|
|
1356
1379
|
AsyncCall(Napi::Env env, InstanceData *instance, const FunctionInfo *func,
|
|
1357
|
-
InstanceMemory *mem, Napi::Function &callback)
|
|
1358
|
-
: Napi::AsyncWorker(callback), env(env), func(func->Ref()),
|
|
1380
|
+
void *native, InstanceMemory *mem, Napi::Function &callback)
|
|
1381
|
+
: Napi::AsyncWorker(callback), env(env), func(func->Ref()), native(native),
|
|
1359
1382
|
call(env, instance, mem) {}
|
|
1360
1383
|
~AsyncCall() { func->Unref(); }
|
|
1361
1384
|
|
|
@@ -1381,7 +1404,7 @@ void AsyncCall::Execute()
|
|
|
1381
1404
|
RG_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1382
1405
|
exec_call = &call;
|
|
1383
1406
|
|
|
1384
|
-
call.Execute(func);
|
|
1407
|
+
call.Execute(func, native);
|
|
1385
1408
|
}
|
|
1386
1409
|
}
|
|
1387
1410
|
|
|
@@ -1400,18 +1423,20 @@ void AsyncCall::OnOK()
|
|
|
1400
1423
|
callback.Call(self, RG_LEN(args), args);
|
|
1401
1424
|
}
|
|
1402
1425
|
|
|
1403
|
-
static Napi::Value TranslateAsyncCall(const
|
|
1426
|
+
static Napi::Value TranslateAsyncCall(const FunctionInfo *func, void *native,
|
|
1427
|
+
const Napi::CallbackInfo &info)
|
|
1404
1428
|
{
|
|
1429
|
+
RG_ASSERT(!func->variadic);
|
|
1430
|
+
|
|
1405
1431
|
Napi::Env env = info.Env();
|
|
1406
1432
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1407
|
-
FunctionInfo *func = (FunctionInfo *)info.Data();
|
|
1408
1433
|
|
|
1409
|
-
if (info.Length() <= (uint32_t)func->
|
|
1434
|
+
if (info.Length() <= (uint32_t)func->required_parameters) {
|
|
1410
1435
|
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len + 1, info.Length());
|
|
1411
1436
|
return env.Null();
|
|
1412
1437
|
}
|
|
1413
1438
|
|
|
1414
|
-
Napi::Function callback = info[(uint32_t)func->
|
|
1439
|
+
Napi::Function callback = info[(uint32_t)func->required_parameters].As<Napi::Function>();
|
|
1415
1440
|
|
|
1416
1441
|
if (!callback.IsFunction()) {
|
|
1417
1442
|
ThrowError<Napi::TypeError>(env, "Expected callback function as last argument, got %1", GetValueType(instance, callback));
|
|
@@ -1423,7 +1448,7 @@ static Napi::Value TranslateAsyncCall(const Napi::CallbackInfo &info)
|
|
|
1423
1448
|
ThrowError<Napi::Error>(env, "Too many asynchronous calls are running");
|
|
1424
1449
|
return env.Null();
|
|
1425
1450
|
}
|
|
1426
|
-
AsyncCall *async = new AsyncCall(env, instance, func, mem, callback);
|
|
1451
|
+
AsyncCall *async = new AsyncCall(env, instance, func, native, mem, callback);
|
|
1427
1452
|
|
|
1428
1453
|
if (async->Prepare(info) && instance->debug) {
|
|
1429
1454
|
async->DumpForward();
|
|
@@ -1433,6 +1458,12 @@ static Napi::Value TranslateAsyncCall(const Napi::CallbackInfo &info)
|
|
|
1433
1458
|
return env.Undefined();
|
|
1434
1459
|
}
|
|
1435
1460
|
|
|
1461
|
+
static Napi::Value TranslateAsyncCall(const Napi::CallbackInfo &info)
|
|
1462
|
+
{
|
|
1463
|
+
FunctionInfo *func = (FunctionInfo *)info.Data();
|
|
1464
|
+
return TranslateAsyncCall(func, func->native, info);
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1436
1467
|
static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConvention convention)
|
|
1437
1468
|
{
|
|
1438
1469
|
Napi::Env env = info.Env();
|
|
@@ -1478,36 +1509,44 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConve
|
|
|
1478
1509
|
#ifdef _WIN32
|
|
1479
1510
|
if (info[0].IsString()) {
|
|
1480
1511
|
if (func->decorated_name) {
|
|
1481
|
-
func->
|
|
1512
|
+
func->native = (void *)GetProcAddress((HMODULE)lib->module, func->decorated_name);
|
|
1482
1513
|
}
|
|
1483
|
-
if (!func->
|
|
1484
|
-
func->
|
|
1514
|
+
if (!func->native) {
|
|
1515
|
+
func->native = (void *)GetProcAddress((HMODULE)lib->module, func->name);
|
|
1485
1516
|
}
|
|
1486
1517
|
} else {
|
|
1487
1518
|
uint16_t ordinal = (uint16_t)info[0].As<Napi::Number>().Uint32Value();
|
|
1488
1519
|
|
|
1489
1520
|
func->decorated_name = nullptr;
|
|
1490
|
-
func->
|
|
1521
|
+
func->native = (void *)GetProcAddress((HMODULE)lib->module, (LPCSTR)(size_t)ordinal);
|
|
1491
1522
|
}
|
|
1492
1523
|
#else
|
|
1493
1524
|
if (func->decorated_name) {
|
|
1494
|
-
func->
|
|
1525
|
+
func->native = dlsym(lib->module, func->decorated_name);
|
|
1495
1526
|
}
|
|
1496
|
-
if (!func->
|
|
1497
|
-
func->
|
|
1527
|
+
if (!func->native) {
|
|
1528
|
+
func->native = dlsym(lib->module, func->name);
|
|
1498
1529
|
}
|
|
1499
1530
|
#endif
|
|
1500
|
-
if (!func->
|
|
1531
|
+
if (!func->native) {
|
|
1501
1532
|
ThrowError<Napi::Error>(env, "Cannot find function '%1' in shared library", func->name);
|
|
1502
1533
|
return env.Null();
|
|
1503
1534
|
}
|
|
1504
1535
|
|
|
1505
|
-
Napi::Function
|
|
1506
|
-
|
|
1536
|
+
Napi::Function wrapper;
|
|
1537
|
+
if (func->variadic) {
|
|
1538
|
+
Napi::Function::Callback call = TranslateVariadicCall;
|
|
1539
|
+
wrapper = Napi::Function::New(env, call, func->name, (void *)func->Ref());
|
|
1540
|
+
} else {
|
|
1541
|
+
Napi::Function::Callback call = TranslateNormalCall;
|
|
1542
|
+
wrapper = Napi::Function::New(env, call, func->name, (void *)func->Ref());
|
|
1543
|
+
}
|
|
1507
1544
|
wrapper.AddFinalizer([](Napi::Env, FunctionInfo *func) { func->Unref(); }, func);
|
|
1508
1545
|
|
|
1509
1546
|
if (!func->variadic) {
|
|
1510
|
-
Napi::Function
|
|
1547
|
+
Napi::Function::Callback call = TranslateAsyncCall;
|
|
1548
|
+
Napi::Function async = Napi::Function::New(env, call, func->name, (void *)func->Ref());
|
|
1549
|
+
|
|
1511
1550
|
async.AddFinalizer([](Napi::Env, FunctionInfo *func) { func->Unref(); }, func);
|
|
1512
1551
|
wrapper.Set("async", async);
|
|
1513
1552
|
}
|
|
@@ -2064,6 +2103,69 @@ static Napi::Value GetPointerAddress(const Napi::CallbackInfo &info)
|
|
|
2064
2103
|
return bigint;
|
|
2065
2104
|
}
|
|
2066
2105
|
|
|
2106
|
+
static Napi::Value CallPointerSync(const Napi::CallbackInfo &info)
|
|
2107
|
+
{
|
|
2108
|
+
Napi::Env env = info.Env();
|
|
2109
|
+
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
2110
|
+
|
|
2111
|
+
if (RG_UNLIKELY(info.Length() < 2)) {
|
|
2112
|
+
ThrowError<Napi::TypeError>(env, "Expected 2 or more arguments, got %1", info.Length());
|
|
2113
|
+
return env.Null();
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
void *ptr = nullptr;
|
|
2117
|
+
if (RG_UNLIKELY(!GetExternalPointer(env, info[0], &ptr)))
|
|
2118
|
+
return env.Null();
|
|
2119
|
+
|
|
2120
|
+
const TypeInfo *type = ResolveType(info[1]);
|
|
2121
|
+
if (RG_UNLIKELY(!type))
|
|
2122
|
+
return env.Null();
|
|
2123
|
+
if (RG_UNLIKELY(type->primitive != PrimitiveKind::Callback)) {
|
|
2124
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for type, expected function pointer type", GetValueType(instance, info[1]));
|
|
2125
|
+
return env.Null();
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
const FunctionInfo *proto = type->ref.proto;
|
|
2129
|
+
|
|
2130
|
+
if (proto->variadic) {
|
|
2131
|
+
return TranslateVariadicCall(proto, ptr, info);
|
|
2132
|
+
} else {
|
|
2133
|
+
return TranslateNormalCall(proto, ptr, info);
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
static Napi::Value CallPointerAsync(const Napi::CallbackInfo &info)
|
|
2138
|
+
{
|
|
2139
|
+
Napi::Env env = info.Env();
|
|
2140
|
+
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
2141
|
+
|
|
2142
|
+
if (RG_UNLIKELY(info.Length() < 2)) {
|
|
2143
|
+
ThrowError<Napi::TypeError>(env, "Expected 2 or more arguments, got %1", info.Length());
|
|
2144
|
+
return env.Null();
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
void *ptr = nullptr;
|
|
2148
|
+
if (RG_UNLIKELY(!GetExternalPointer(env, info[0], &ptr)))
|
|
2149
|
+
return env.Null();
|
|
2150
|
+
|
|
2151
|
+
const TypeInfo *type = ResolveType(info[1]);
|
|
2152
|
+
if (RG_UNLIKELY(!type))
|
|
2153
|
+
return env.Null();
|
|
2154
|
+
if (RG_UNLIKELY(type->primitive != PrimitiveKind::Callback)) {
|
|
2155
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for type, expected function pointer type", GetValueType(instance, info[1]));
|
|
2156
|
+
return env.Null();
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
const FunctionInfo *proto = type->ref.proto;
|
|
2160
|
+
|
|
2161
|
+
if (RG_UNLIKELY(proto->variadic)) {
|
|
2162
|
+
ThrowError<Napi::TypeError>(env, "Cannot call variadic function asynchronously");
|
|
2163
|
+
return env.Null();
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
return TranslateAsyncCall(proto, ptr, info);
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2067
2169
|
extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
|
|
2068
2170
|
{
|
|
2069
2171
|
if (RG_LIKELY(exec_call)) {
|
|
@@ -2106,7 +2208,7 @@ static void SetExports(Napi::Env env, Func func)
|
|
|
2106
2208
|
func("opaque", Napi::Function::New(env, CreateOpaqueType));
|
|
2107
2209
|
func("pointer", Napi::Function::New(env, CreatePointerType));
|
|
2108
2210
|
func("array", Napi::Function::New(env, CreateArrayType));
|
|
2109
|
-
func("
|
|
2211
|
+
func("proto", Napi::Function::New(env, CreateFunctionType));
|
|
2110
2212
|
func("alias", Napi::Function::New(env, CreateTypeAlias));
|
|
2111
2213
|
|
|
2112
2214
|
func("sizeof", Napi::Function::New(env, GetTypeSize));
|
|
@@ -2130,6 +2232,8 @@ static void SetExports(Napi::Env env, Func func)
|
|
|
2130
2232
|
func("as", Napi::Function::New(env, CastValue));
|
|
2131
2233
|
func("decode", Napi::Function::New(env, DecodeValue));
|
|
2132
2234
|
func("address", Napi::Function::New(env, GetPointerAddress));
|
|
2235
|
+
func("call", Napi::Function::New(env, CallPointerSync));
|
|
2236
|
+
func("callAsync", Napi::Function::New(env, CallPointerAsync));
|
|
2133
2237
|
|
|
2134
2238
|
func("errno", Napi::Function::New(env, GetOrSetErrNo));
|
|
2135
2239
|
|
package/src/koffi/src/ffi.hh
CHANGED
|
@@ -221,11 +221,12 @@ struct FunctionInfo {
|
|
|
221
221
|
const char *decorated_name; // Only set for some platforms/calling conventions
|
|
222
222
|
const LibraryHolder *lib = nullptr;
|
|
223
223
|
|
|
224
|
-
void *
|
|
224
|
+
void *native;
|
|
225
225
|
CallConvention convention;
|
|
226
226
|
|
|
227
227
|
ParameterInfo ret;
|
|
228
228
|
HeapArray<ParameterInfo> parameters;
|
|
229
|
+
int8_t required_parameters;
|
|
229
230
|
int8_t out_parameters;
|
|
230
231
|
bool variadic;
|
|
231
232
|
|
package/src/koffi/src/parser.cc
CHANGED
|
@@ -99,6 +99,8 @@ bool PrototypeParser::Parse(const char *str, FunctionInfo *out_func)
|
|
|
99
99
|
}
|
|
100
100
|
Consume(")");
|
|
101
101
|
|
|
102
|
+
out_func->required_parameters = (int8_t)out_func->parameters.len;
|
|
103
|
+
|
|
102
104
|
Match(";");
|
|
103
105
|
if (offset < tokens.len) {
|
|
104
106
|
MarkError("Unexpected token '%1' after prototype", tokens[offset]);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|