koffi 1.1.0-beta.2 → 1.1.0-beta.5

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/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  - [Introduction](#introduction)
4
4
  - [Get started](#get-started)
5
5
  - [Extra features](#extra-features)
6
+ * [Type information](#type-information)
6
7
  * [C arrays](#c-arrays)
7
8
  * [Variadic functions](#variadic-functions)
8
9
  * [Asynchronous calls](#asynchronous-calls)
@@ -218,6 +219,13 @@ while (!WindowShouldClose()) {
218
219
 
219
220
  # Extra features
220
221
 
222
+ ## Type information
223
+
224
+ Koffi exposes three functions to explore type information:
225
+ - `koffi.sizeof(type)` to get the size of a type
226
+ - `koffi.alignof(type)` to get the alignment of a type
227
+ - `koffi.introspect(type)` to get the definition of a type (only for structs for now)
228
+
221
229
  ## C arrays
222
230
 
223
231
  Fixed-size arrays are declared with `koffi.array(type, length)`. Just like in C, they cannot be passed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "1.1.0-beta.2",
3
+ "version": "1.1.0-beta.5",
4
4
  "description": "Fast and simple FFI (foreign function interface) for Node.js",
5
5
  "keywords": [
6
6
  "foreign",
package/src/ffi.cc CHANGED
@@ -72,6 +72,8 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
72
72
 
73
73
  type->name = DuplicateString(name.c_str(), &instance->str_alloc).ptr;
74
74
 
75
+ type->defn.Reset(obj, 1);
76
+
75
77
  type->primitive = PrimitiveKind::Record;
76
78
  type->align = 1;
77
79
 
@@ -296,6 +298,61 @@ static Napi::Value CreateArrayType(const Napi::CallbackInfo &info)
296
298
  return external;
297
299
  }
298
300
 
301
+ static Napi::Value GetTypeSize(const Napi::CallbackInfo &info)
302
+ {
303
+ Napi::Env env = info.Env();
304
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
305
+
306
+ if (info.Length() < 1) {
307
+ ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
308
+ return env.Null();
309
+ }
310
+
311
+ const TypeInfo *type = ResolveType(instance, info[0]);
312
+ if (!type)
313
+ return env.Null();
314
+
315
+ return Napi::Number::New(env, type->size);
316
+ }
317
+
318
+ static Napi::Value GetTypeAlign(const Napi::CallbackInfo &info)
319
+ {
320
+ Napi::Env env = info.Env();
321
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
322
+
323
+ if (info.Length() < 1) {
324
+ ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
325
+ return env.Null();
326
+ }
327
+
328
+ const TypeInfo *type = ResolveType(instance, info[0]);
329
+ if (!type)
330
+ return env.Null();
331
+
332
+ return Napi::Number::New(env, type->align);
333
+ }
334
+
335
+ static Napi::Value GetTypeDefinition(const Napi::CallbackInfo &info)
336
+ {
337
+ Napi::Env env = info.Env();
338
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
339
+
340
+ if (info.Length() < 1) {
341
+ ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
342
+ return env.Null();
343
+ }
344
+
345
+ const TypeInfo *type = ResolveType(instance, info[0]);
346
+ if (!type)
347
+ return env.Null();
348
+ if (type->defn.IsEmpty()) {
349
+ ThrowError<Napi::TypeError>(env, "Definition of type %1 is not available", type->name);
350
+ return env.Null();
351
+ }
352
+
353
+ return type->defn.Value();
354
+ }
355
+
299
356
  static Span<uint8_t> AllocateAndAlign16(Allocator *alloc, Size size)
300
357
  {
301
358
  RG_ASSERT(AlignLen(size, 16) == size);
@@ -539,8 +596,9 @@ static bool ParseClassicFunction(Napi::Env env, Napi::String name, Napi::Value r
539
596
  param.type = ResolveType(instance, parameters[j], &param.directions);
540
597
  if (!param.type)
541
598
  return false;
542
- if (param.type->primitive == PrimitiveKind::Void) {
543
- ThrowError<Napi::TypeError>(env, "Type void cannot be used as a parameter");
599
+ if (param.type->primitive == PrimitiveKind::Void ||
600
+ param.type->primitive == PrimitiveKind::Array) {
601
+ ThrowError<Napi::TypeError>(env, "Type %1 cannot be used as a parameter", param.type->name);
544
602
  return false;
545
603
  }
546
604
 
@@ -869,6 +927,9 @@ static void SetExports(Napi::Env env, Func func)
869
927
  func("handle", Napi::Function::New(env, CreateHandleType));
870
928
  func("pointer", Napi::Function::New(env, CreatePointerType));
871
929
  func("array", Napi::Function::New(env, CreateArrayType));
930
+ func("sizeof", Napi::Function::New(env, GetTypeSize));
931
+ func("alignof", Napi::Function::New(env, GetTypeAlign));
932
+ func("introspect", Napi::Function::New(env, GetTypeDefinition));
872
933
  func("load", Napi::Function::New(env, LoadSharedLibrary));
873
934
  func("in", Napi::Function::New(env, MarkIn));
874
935
  func("out", Napi::Function::New(env, MarkOut));
package/src/ffi.hh CHANGED
@@ -70,6 +70,8 @@ struct TypeInfo {
70
70
  const char *name;
71
71
  napi_type_tag tag;
72
72
 
73
+ Napi::ObjectReference defn;
74
+
73
75
  PrimitiveKind primitive;
74
76
  int16_t size;
75
77
  int16_t align;
package/src/parser.cc CHANGED
@@ -36,7 +36,7 @@ bool PrototypeParser::Parse(Napi::String proto, FunctionInfo *func)
36
36
 
37
37
  func->ret.type = ParseType();
38
38
  if (func->ret.type->primitive == PrimitiveKind::Array) {
39
- MarkError("You are not allowed to directly return fixed-size arrays");
39
+ MarkError("You are not allowed to directly return C arrays");
40
40
  return false;
41
41
  }
42
42
  if (Match("__cdecl")) {
@@ -69,8 +69,9 @@ bool PrototypeParser::Parse(Napi::String proto, FunctionInfo *func)
69
69
  }
70
70
 
71
71
  param.type = ParseType();
72
- if (param.type->primitive == PrimitiveKind::Void) {
73
- MarkError("Type void cannot be used as a parameter");
72
+ if (param.type->primitive == PrimitiveKind::Void ||
73
+ param.type->primitive == PrimitiveKind::Array) {
74
+ MarkError("Type %1 cannot be used as a parameter", param.type->name);
74
75
  return false;
75
76
  }
76
77