koffi 2.3.16 → 2.3.17
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/CHANGELOG.md +8 -1
- package/build/2.3.17/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.17/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.17/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.17/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.17/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.17/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.17/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.17/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.17/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/2.3.17/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.17/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.17/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.17/koffi_win32_arm64/koffi.node +0 -0
- package/build/2.3.17/koffi_win32_ia32/koffi.node +0 -0
- package/build/{2.3.16 → 2.3.17}/koffi_win32_x64/koffi.node +0 -0
- package/package.json +2 -2
- package/src/koffi/src/call.cc +118 -24
- package/src/koffi/src/call.hh +13 -0
- package/src/koffi/src/ffi.cc +11 -7
- package/src/koffi/src/util.cc +1 -1
- package/src/koffi/src/util.hh +2 -0
- package/build/2.3.16/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.16/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.16/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.16/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.16/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.16/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.16/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.16/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.16/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/2.3.16/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.16/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.16/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.16/koffi_win32_arm64/koffi.node +0 -0
- package/build/2.3.16/koffi_win32_ia32/koffi.node +0 -0
- /package/build/{2.3.16 → 2.3.17}/koffi_win32_arm64/koffi.exp +0 -0
- /package/build/{2.3.16 → 2.3.17}/koffi_win32_arm64/koffi.lib +0 -0
- /package/build/{2.3.16 → 2.3.17}/koffi_win32_ia32/koffi.exp +0 -0
- /package/build/{2.3.16 → 2.3.17}/koffi_win32_ia32/koffi.lib +0 -0
- /package/build/{2.3.16 → 2.3.17}/koffi_win32_x64/koffi.exp +0 -0
- /package/build/{2.3.16 → 2.3.17}/koffi_win32_x64/koffi.lib +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
### Koffi 2.3
|
|
6
6
|
|
|
7
|
+
#### Koffi 2.3.17
|
|
8
|
+
|
|
9
|
+
**Main changes:**
|
|
10
|
+
|
|
11
|
+
- Allow strings for input `void *`, `int8_t *` and `int16_t *` pointer arguments
|
|
12
|
+
- Support using `[string]` (single-element string arrays) for polymorphic input/output arguments
|
|
13
|
+
|
|
7
14
|
#### Koffi 2.3.16
|
|
8
15
|
|
|
9
16
|
**Main changes:**
|
|
@@ -13,7 +20,7 @@
|
|
|
13
20
|
|
|
14
21
|
**Other changes:**
|
|
15
22
|
|
|
16
|
-
- Support null in koffi.free() and koffi.address()
|
|
23
|
+
- Support null in `koffi.free()` and `koffi.address()`
|
|
17
24
|
|
|
18
25
|
#### Koffi 2.3.15
|
|
19
26
|
|
|
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/koffi/src/call.cc
CHANGED
|
@@ -147,7 +147,7 @@ bool CallData::PushString(Napi::Value value, int directions, const char **out_st
|
|
|
147
147
|
{
|
|
148
148
|
if (value.IsString()) {
|
|
149
149
|
if (RG_UNLIKELY(directions & 2)) {
|
|
150
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
|
|
150
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, value));
|
|
151
151
|
return false;
|
|
152
152
|
}
|
|
153
153
|
|
|
@@ -200,6 +200,7 @@ bool CallData::PushString(Napi::Value value, int directions, const char **out_st
|
|
|
200
200
|
napi_status status = napi_create_reference(env, array, 1, &out->ref);
|
|
201
201
|
RG_ASSERT(status == napi_ok);
|
|
202
202
|
|
|
203
|
+
out->kind = OutArgument::Kind::Array;
|
|
203
204
|
out->ptr = (const uint8_t *)*out_str;
|
|
204
205
|
out->type = type;
|
|
205
206
|
}
|
|
@@ -301,6 +302,7 @@ bool CallData::PushString16(Napi::Value value, int directions, const char16_t **
|
|
|
301
302
|
napi_status status = napi_create_reference(env, array, 1, &out->ref);
|
|
302
303
|
RG_ASSERT(status == napi_ok);
|
|
303
304
|
|
|
305
|
+
out->kind = OutArgument::Kind::Array;
|
|
304
306
|
out->ptr = (const uint8_t *)*out_str16;
|
|
305
307
|
out->type = type;
|
|
306
308
|
}
|
|
@@ -973,6 +975,9 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
973
975
|
case napi_object: {
|
|
974
976
|
uint8_t *ptr = nullptr;
|
|
975
977
|
|
|
978
|
+
OutArgument::Kind out_kind;
|
|
979
|
+
Size out_max_len = -1;
|
|
980
|
+
|
|
976
981
|
if (value.IsArray()) {
|
|
977
982
|
if (RG_UNLIKELY(!type->ref.type->size)) {
|
|
978
983
|
ThrowError<Napi::TypeError>(env, "Cannot pass %1 value to void *, use koffi.as()",
|
|
@@ -981,17 +986,25 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
981
986
|
}
|
|
982
987
|
|
|
983
988
|
Napi::Array array = value.As<Napi::Array>();
|
|
989
|
+
Size len = PushIndirectString(array, type->ref.type, &ptr);
|
|
984
990
|
|
|
985
|
-
|
|
986
|
-
|
|
991
|
+
if (len >= 0) {
|
|
992
|
+
out_kind = (type->ref.type->size == 2) ? OutArgument::Kind::String16 : OutArgument::Kind::String;
|
|
993
|
+
out_max_len = len;
|
|
994
|
+
} else {
|
|
995
|
+
Size len = (Size)array.Length();
|
|
996
|
+
Size size = len * type->ref.type->size;
|
|
987
997
|
|
|
988
|
-
|
|
998
|
+
ptr = AllocHeap(size, 16);
|
|
989
999
|
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1000
|
+
if (directions & 1) {
|
|
1001
|
+
if (!PushNormalArray(array, len, type, ptr))
|
|
1002
|
+
return false;
|
|
1003
|
+
} else {
|
|
1004
|
+
memset_safe(ptr, 0, size);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
out_kind = OutArgument::Kind::Array;
|
|
995
1008
|
}
|
|
996
1009
|
} else if (IsRawBuffer(value)) {
|
|
997
1010
|
Span<uint8_t> buffer = GetRawBuffer(value);
|
|
@@ -1006,6 +1019,8 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
1006
1019
|
ptr = buffer.ptr;
|
|
1007
1020
|
directions = 1;
|
|
1008
1021
|
}
|
|
1022
|
+
|
|
1023
|
+
out_kind = OutArgument::Kind::Buffer;
|
|
1009
1024
|
} else if (RG_LIKELY(type->ref.type->primitive == PrimitiveKind::Record ||
|
|
1010
1025
|
type->ref.type->primitive == PrimitiveKind::Union)) {
|
|
1011
1026
|
if (RG_UNLIKELY(!type->ref.type->size)) {
|
|
@@ -1031,6 +1046,8 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
1031
1046
|
|
|
1032
1047
|
memset_safe(ptr, 0, type->size);
|
|
1033
1048
|
}
|
|
1049
|
+
|
|
1050
|
+
out_kind = OutArgument::Kind::Object;
|
|
1034
1051
|
} else {
|
|
1035
1052
|
goto unexpected;
|
|
1036
1053
|
}
|
|
@@ -1041,14 +1058,36 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
1041
1058
|
napi_status status = napi_create_reference(env, value, 1, &out->ref);
|
|
1042
1059
|
RG_ASSERT(status == napi_ok);
|
|
1043
1060
|
|
|
1061
|
+
out->kind = out_kind;
|
|
1044
1062
|
out->ptr = ptr;
|
|
1045
1063
|
out->type = type->ref.type;
|
|
1064
|
+
out->max_len = out_max_len;
|
|
1046
1065
|
}
|
|
1047
1066
|
|
|
1048
1067
|
*out_ptr = ptr;
|
|
1049
1068
|
return true;
|
|
1050
1069
|
} break;
|
|
1051
1070
|
|
|
1071
|
+
case napi_string: {
|
|
1072
|
+
RG_ASSERT(type->primitive == PrimitiveKind::Pointer);
|
|
1073
|
+
|
|
1074
|
+
if (RG_UNLIKELY(directions & 2))
|
|
1075
|
+
goto unexpected;
|
|
1076
|
+
|
|
1077
|
+
if (type->ref.type == instance->void_type) {
|
|
1078
|
+
PushStringValue(value, (const char **)out_ptr);
|
|
1079
|
+
return true;
|
|
1080
|
+
} else if (type->ref.type->primitive == PrimitiveKind::Int8) {
|
|
1081
|
+
PushStringValue(value, (const char **)out_ptr);
|
|
1082
|
+
return true;
|
|
1083
|
+
} else if (type->ref.type->primitive == PrimitiveKind::Int16) {
|
|
1084
|
+
PushString16Value(value, (const char16_t **)out_ptr);
|
|
1085
|
+
return true;
|
|
1086
|
+
} else {
|
|
1087
|
+
goto unexpected;
|
|
1088
|
+
}
|
|
1089
|
+
} break;
|
|
1090
|
+
|
|
1052
1091
|
case napi_number: {
|
|
1053
1092
|
Napi::Number number = value.As<Napi::Number>();
|
|
1054
1093
|
intptr_t ptr = (intptr_t)number.Int32Value();
|
|
@@ -1075,6 +1114,27 @@ unexpected:
|
|
|
1075
1114
|
return false;
|
|
1076
1115
|
}
|
|
1077
1116
|
|
|
1117
|
+
Size CallData::PushIndirectString(Napi::Array array, const TypeInfo *ref, uint8_t **out_ptr)
|
|
1118
|
+
{
|
|
1119
|
+
if (array.Length() != 1)
|
|
1120
|
+
return -1;
|
|
1121
|
+
|
|
1122
|
+
Napi::Value value = array[0u];
|
|
1123
|
+
|
|
1124
|
+
if (!value.IsString())
|
|
1125
|
+
return -1;
|
|
1126
|
+
|
|
1127
|
+
if (ref == instance->void_type) {
|
|
1128
|
+
return PushStringValue(value, (const char **)out_ptr);
|
|
1129
|
+
} else if (ref->primitive == PrimitiveKind::Int8) {
|
|
1130
|
+
return PushStringValue(value, (const char **)out_ptr);
|
|
1131
|
+
} else if (ref->primitive == PrimitiveKind::Int16) {
|
|
1132
|
+
return PushString16Value(value, (const char16_t **)out_ptr);
|
|
1133
|
+
} else {
|
|
1134
|
+
return -1;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1078
1138
|
static inline Napi::Value GetReferenceValue(Napi::Env env, napi_ref ref)
|
|
1079
1139
|
{
|
|
1080
1140
|
napi_value value;
|
|
@@ -1091,21 +1151,55 @@ void CallData::PopOutArguments()
|
|
|
1091
1151
|
Napi::Value value = GetReferenceValue(env, out.ref);
|
|
1092
1152
|
RG_ASSERT(!value.IsEmpty());
|
|
1093
1153
|
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1154
|
+
switch (out.kind) {
|
|
1155
|
+
case OutArgument::Kind::Array: {
|
|
1156
|
+
RG_ASSERT(value.IsArray());
|
|
1157
|
+
|
|
1158
|
+
Napi::Array array(env, value);
|
|
1159
|
+
DecodeNormalArray(array, out.ptr, out.type);
|
|
1160
|
+
} break;
|
|
1161
|
+
|
|
1162
|
+
case OutArgument::Kind::Buffer: {
|
|
1163
|
+
RG_ASSERT(IsRawBuffer(value));
|
|
1164
|
+
|
|
1165
|
+
Span<uint8_t> buffer = GetRawBuffer(value);
|
|
1166
|
+
DecodeBuffer(buffer, out.ptr, out.type);
|
|
1167
|
+
} break;
|
|
1168
|
+
|
|
1169
|
+
case OutArgument::Kind::String: {
|
|
1170
|
+
Napi::Array array(env, value);
|
|
1171
|
+
|
|
1172
|
+
RG_ASSERT(array.IsArray());
|
|
1173
|
+
RG_ASSERT(array.Length() == 1);
|
|
1174
|
+
|
|
1175
|
+
Size len = strnlen((const char *)out.ptr, out.max_len);
|
|
1176
|
+
Napi::String str = Napi::String::New(env, (const char *)out.ptr, len);
|
|
1177
|
+
|
|
1178
|
+
array.Set(0u, str);
|
|
1179
|
+
} break;
|
|
1180
|
+
|
|
1181
|
+
case OutArgument::Kind::String16: {
|
|
1182
|
+
Napi::Array array(env, value);
|
|
1183
|
+
|
|
1184
|
+
RG_ASSERT(array.IsArray());
|
|
1185
|
+
RG_ASSERT(array.Length() == 1);
|
|
1186
|
+
|
|
1187
|
+
Size len = WideStringLength((const char16_t *)out.ptr, out.max_len);
|
|
1188
|
+
Napi::String str = Napi::String::New(env, (const char16_t *)out.ptr, len);
|
|
1189
|
+
|
|
1190
|
+
array.Set(0u, str);
|
|
1191
|
+
} break;
|
|
1192
|
+
|
|
1193
|
+
case OutArgument::Kind::Object: {
|
|
1194
|
+
Napi::Object obj = value.As<Napi::Object>();
|
|
1195
|
+
|
|
1196
|
+
if (CheckValueTag(instance, value, &MagicUnionMarker)) {
|
|
1197
|
+
MagicUnion *u = MagicUnion::Unwrap(obj);
|
|
1198
|
+
u->SetRaw(out.ptr);
|
|
1199
|
+
} else {
|
|
1200
|
+
DecodeObject(obj, out.ptr, out.type);
|
|
1201
|
+
}
|
|
1202
|
+
} break;
|
|
1109
1203
|
}
|
|
1110
1204
|
}
|
|
1111
1205
|
}
|
package/src/koffi/src/call.hh
CHANGED
|
@@ -37,9 +37,21 @@ struct BackRegisters;
|
|
|
37
37
|
// But on Windows i386, without it, the alignment may not be correct (compiler bug?).
|
|
38
38
|
class alignas(8) CallData {
|
|
39
39
|
struct OutArgument {
|
|
40
|
+
enum class Kind {
|
|
41
|
+
Array,
|
|
42
|
+
Buffer,
|
|
43
|
+
String,
|
|
44
|
+
String16,
|
|
45
|
+
Object
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
Kind kind;
|
|
49
|
+
|
|
40
50
|
napi_ref ref;
|
|
41
51
|
const uint8_t *ptr;
|
|
42
52
|
const TypeInfo *type;
|
|
53
|
+
|
|
54
|
+
Size max_len; // Only for indirect strings
|
|
43
55
|
};
|
|
44
56
|
|
|
45
57
|
Napi::Env env;
|
|
@@ -116,6 +128,7 @@ private:
|
|
|
116
128
|
bool PushBuffer(Span<const uint8_t> buffer, Size size, const TypeInfo *type, uint8_t *origin);
|
|
117
129
|
bool PushStringArray(Napi::Value value, const TypeInfo *type, uint8_t *origin);
|
|
118
130
|
bool PushPointer(Napi::Value value, const TypeInfo *type, int directions, void **out_ptr);
|
|
131
|
+
Size PushIndirectString(Napi::Array array, const TypeInfo *ref, uint8_t **out_ptr);
|
|
119
132
|
|
|
120
133
|
void PopOutArguments();
|
|
121
134
|
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -605,8 +605,10 @@ static Napi::Value EncodePointerDirection(const Napi::CallbackInfo &info, int di
|
|
|
605
605
|
if (!type)
|
|
606
606
|
return env.Null();
|
|
607
607
|
|
|
608
|
-
if (type->primitive != PrimitiveKind::Pointer
|
|
609
|
-
|
|
608
|
+
if (type->primitive != PrimitiveKind::Pointer &&
|
|
609
|
+
type->primitive != PrimitiveKind::String &&
|
|
610
|
+
type->primitive != PrimitiveKind::String16) {
|
|
611
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 type, expected pointer or string type", type->name);
|
|
610
612
|
return env.Null();
|
|
611
613
|
}
|
|
612
614
|
|
|
@@ -653,9 +655,9 @@ static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
|
|
|
653
655
|
const TypeInfo *src = ResolveType(info[named]);
|
|
654
656
|
if (!src)
|
|
655
657
|
return env.Null();
|
|
656
|
-
if (src->primitive != PrimitiveKind::
|
|
657
|
-
src->primitive != PrimitiveKind::
|
|
658
|
-
src->primitive != PrimitiveKind::
|
|
658
|
+
if (src->primitive != PrimitiveKind::Pointer &&
|
|
659
|
+
src->primitive != PrimitiveKind::String &&
|
|
660
|
+
src->primitive != PrimitiveKind::String16) {
|
|
659
661
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 type, expected pointer or string type", src->name);
|
|
660
662
|
return env.Null();
|
|
661
663
|
}
|
|
@@ -1982,8 +1984,10 @@ static Napi::Value CastValue(const Napi::CallbackInfo &info)
|
|
|
1982
1984
|
const TypeInfo *type = ResolveType(info[1]);
|
|
1983
1985
|
if (RG_UNLIKELY(!type))
|
|
1984
1986
|
return env.Null();
|
|
1985
|
-
if (type->primitive != PrimitiveKind::Pointer
|
|
1986
|
-
|
|
1987
|
+
if (type->primitive != PrimitiveKind::Pointer &&
|
|
1988
|
+
type->primitive != PrimitiveKind::String &&
|
|
1989
|
+
type->primitive != PrimitiveKind::String16) {
|
|
1990
|
+
ThrowError<Napi::TypeError>(env, "Only pointer or string types can be used for casting");
|
|
1987
1991
|
return env.Null();
|
|
1988
1992
|
}
|
|
1989
1993
|
|
package/src/koffi/src/util.cc
CHANGED
package/src/koffi/src/util.hh
CHANGED
|
@@ -154,6 +154,8 @@ T GetNumber(Napi::Value value)
|
|
|
154
154
|
RG_UNREACHABLE();
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
Size WideStringLength(const char16_t *str16, Size max);
|
|
158
|
+
|
|
157
159
|
Napi::Object DecodeObject(Napi::Env env, const uint8_t *origin, const TypeInfo *type);
|
|
158
160
|
void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type);
|
|
159
161
|
Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type);
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|