node-ctypes 0.1.7 → 1.0.0

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.

Potentially problematic release.


This version of node-ctypes might be problematic. Click here for more details.

@@ -0,0 +1,140 @@
1
+ /**
2
+ * @file types.js
3
+ * @module core/types
4
+ * @description Type normalization helpers for converting between JavaScript type representations
5
+ * and native FFI type specifications.
6
+ *
7
+ * This module handles the conversion of SimpleCData classes (e.g., c_int32, c_char_p) into
8
+ * the format expected by the native FFI layer. It bridges the gap between the user-facing
9
+ * Python ctypes-compatible API and the underlying libffi implementation.
10
+ *
11
+ * @example
12
+ * ```javascript
13
+ * import { _toNativeType, _toNativeTypes } from './core/types.js';
14
+ * import { c_int32, c_char_p } from './types/integers.js';
15
+ *
16
+ * // Convert single type
17
+ * const nativeType = _toNativeType(c_int32); // Returns "int32"
18
+ *
19
+ * // Convert array of types
20
+ * const nativeTypes = _toNativeTypes([c_int32, c_char_p]);
21
+ * // Returns ["int32", <native CType for c_char_p>]
22
+ * ```
23
+ */
24
+
25
+ /**
26
+ * Converts a SimpleCData class or other type specification to the format required
27
+ * by the native FFI module.
28
+ *
29
+ * **Type Conversion Rules**:
30
+ * 1. **SimpleCData classes** (e.g., `c_int32`, `c_uint64`):
31
+ * - Most types → Convert to string type name (e.g., `"int32"`, `"uint64"`)
32
+ * - `c_char_p` and `c_wchar_p` → Convert to native CType for automatic string marshalling
33
+ *
34
+ * 2. **Structure/Union classes**: Pass through unchanged for struct/union handling
35
+ *
36
+ * 3. **Native CType objects**: Pass through unchanged (already in native format)
37
+ *
38
+ * **Python ctypes Compatibility**:
39
+ * This function mimics Python's ctypes internal type normalization, ensuring that
40
+ * type specifications work consistently whether passed as class constructors or
41
+ * type objects.
42
+ *
43
+ * @param {Function|Object} type - Type specification to normalize
44
+ * - SimpleCData class (e.g., `c_int32`)
45
+ * - Structure or Union class
46
+ * - Native CType object
47
+ * @returns {string|Object} Normalized type for native FFI:
48
+ * - String type name for most SimpleCData types
49
+ * - Native CType object for string pointer types (c_char_p, c_wchar_p)
50
+ * - Original value for Structure/Union/CType objects
51
+ *
52
+ * @example Basic type conversion
53
+ * ```javascript
54
+ * import { c_int32, c_float, c_char_p } from 'node-ctypes';
55
+ *
56
+ * _toNativeType(c_int32); // Returns "int32"
57
+ * _toNativeType(c_float); // Returns "float"
58
+ * _toNativeType(c_char_p); // Returns native.types.c_char_p (CType object)
59
+ * ```
60
+ *
61
+ * @example Structure type pass-through
62
+ * ```javascript
63
+ * import { Structure, c_int32 } from 'node-ctypes';
64
+ *
65
+ * class Point extends Structure {
66
+ * static _fields_ = [['x', c_int32], ['y', c_int32]];
67
+ * }
68
+ *
69
+ * _toNativeType(Point); // Returns Point class unchanged
70
+ * ```
71
+ *
72
+ * @private
73
+ * @internal
74
+ */
75
+ export function _toNativeType(type, native) {
76
+ // SimpleCData classes: convert to string type names or native CTypes
77
+ if (typeof type === "function" && type._isSimpleCData) {
78
+ // String pointer types need native CType for automatic conversion
79
+ // This enables automatic marshalling between C strings and JS strings
80
+ if (type._type === "char_p") return native.types.c_char_p;
81
+ if (type._type === "wchar_p") return native.types.c_wchar_p;
82
+
83
+ // All other SimpleCData types: use string type name
84
+ return type._type;
85
+ }
86
+
87
+ // Structure/Union classes: pass through unchanged
88
+ // These are handled specially by the FFI layer
89
+ if (typeof type === "function" && type.prototype) {
90
+ // Note: We can't directly check "instanceof Structure" here because it would
91
+ // create a circular dependency. The native FFI layer handles this check.
92
+ return type;
93
+ }
94
+
95
+ // Native CType objects: pass through unchanged (already in correct format)
96
+ return type;
97
+ }
98
+
99
+ /**
100
+ * Normalizes an array of type specifications by converting each element using
101
+ * `_toNativeType()`.
102
+ *
103
+ * This is a convenience function for batch type normalization, commonly used when
104
+ * defining function signatures with multiple parameters.
105
+ *
106
+ * **Python ctypes Compatibility**:
107
+ * Equivalent to Python's internal type normalization for argtypes lists.
108
+ *
109
+ * @param {Array|*} types - Array of type specifications, or non-array value
110
+ * @param {Object} native - Native module reference for CType lookups
111
+ * @returns {Array|*} Array of normalized types, or original value if not an array
112
+ *
113
+ * @example Function signature normalization
114
+ * ```javascript
115
+ * import { c_int32, c_char_p, c_void_p } from 'node-ctypes';
116
+ *
117
+ * // Normalize function argument types
118
+ * const argTypes = [c_int32, c_char_p, c_void_p];
119
+ * const normalized = _toNativeTypes(argTypes);
120
+ * // Returns ["int32", <native c_char_p CType>, "void_p"]
121
+ * ```
122
+ *
123
+ * @example Non-array pass-through
124
+ * ```javascript
125
+ * // Non-arrays are returned unchanged
126
+ * _toNativeTypes(null); // Returns null
127
+ * _toNativeTypes(undefined); // Returns undefined
128
+ * _toNativeTypes(c_int32); // Returns c_int32 (not normalized individually)
129
+ * ```
130
+ *
131
+ * @private
132
+ * @internal
133
+ */
134
+ export function _toNativeTypes(types, native) {
135
+ // Non-arrays pass through unchanged
136
+ if (!Array.isArray(types)) return types;
137
+
138
+ // Normalize each type in the array
139
+ return types.map((type) => _toNativeType(type, native));
140
+ }
package/lib/index.d.ts CHANGED
@@ -9,89 +9,14 @@
9
9
  // Basic Types
10
10
  // =============================================================================
11
11
 
12
- /** C type enumeration */
13
- export type CTypeString =
14
- | "void"
15
- | "int8"
16
- | "uint8"
17
- | "int16"
18
- | "uint16"
19
- | "int32"
20
- | "uint32"
21
- | "int64"
22
- | "uint64"
23
- | "float"
24
- | "double"
25
- | "bool"
26
- | "pointer"
27
- | "string"
28
- | "wstring"
29
- | "wchar"
30
- | "size_t"
31
- | "ssize_t"
32
- | "long"
33
- | "ulong"
34
- | "char"
35
- | "uchar"
36
- | "short"
37
- | "ushort"
38
- | "int"
39
- | "uint";
40
-
41
- /** Native CType object */
12
+ /** Native CType object (internal C++ type representation) */
42
13
  export interface CType {
43
14
  readonly size: number;
44
15
  readonly name: string;
45
16
  }
46
17
 
47
- /** Predefined types object */
48
- export interface Types {
49
- readonly void: CType;
50
- readonly int8: CType;
51
- readonly uint8: CType;
52
- readonly int16: CType;
53
- readonly uint16: CType;
54
- readonly int32: CType;
55
- readonly uint32: CType;
56
- readonly int64: CType;
57
- readonly uint64: CType;
58
- readonly float: CType;
59
- readonly double: CType;
60
- readonly bool: CType;
61
- readonly pointer: CType;
62
- readonly string: CType;
63
- readonly wstring: CType;
64
- readonly wchar: CType;
65
- readonly size_t: CType;
66
- readonly long: CType;
67
- readonly ulong: CType;
68
- // Python-style aliases
69
- readonly c_void: CType;
70
- readonly c_int8: CType;
71
- readonly c_uint8: CType;
72
- readonly c_int16: CType;
73
- readonly c_uint16: CType;
74
- readonly c_int32: CType;
75
- readonly c_uint32: CType;
76
- readonly c_int64: CType;
77
- readonly c_uint64: CType;
78
- readonly c_float: CType;
79
- readonly c_double: CType;
80
- readonly c_bool: CType;
81
- readonly c_char_p: CType;
82
- readonly c_wchar_p: CType;
83
- readonly c_wchar: CType;
84
- readonly c_void_p: CType;
85
- readonly c_size_t: CType;
86
- readonly c_long: CType;
87
- readonly c_ulong: CType;
88
- readonly c_int: CType;
89
- readonly c_uint: CType;
90
- readonly c_char: CType;
91
- readonly c_uchar: CType;
92
- readonly c_short: CType;
93
- readonly c_ushort: CType;
94
- }
18
+ /** Any accepted type specification (CType object or SimpleCData class) */
19
+ export type AnyType = CType | SimpleCDataConstructor;
95
20
 
96
21
  // =============================================================================
97
22
  // Library & Function
@@ -108,7 +33,7 @@ export class Version {
108
33
  /** Native library handle */
109
34
  export class Library {
110
35
  constructor(path: string | null);
111
- func(name: string, returnType: CTypeString | CType, argTypes?: (CTypeString | CType)[], options?: FunctionOptions): FFIFunction;
36
+ func(name: string, returnType: AnyType, argTypes?: AnyType[], options?: FunctionOptions): FFIFunction;
112
37
  symbol(name: string): bigint;
113
38
  close(): void;
114
39
  readonly path: string;
@@ -134,7 +59,7 @@ export interface FFIFunction {
134
59
  /** CDLL - C calling convention library */
135
60
  export class CDLL {
136
61
  constructor(path: string | null);
137
- func(name: string, returnType: CTypeString | CType, argTypes?: (CTypeString | CType)[], options?: FunctionOptions): CallableFunction & { errcheck: ErrcheckCallback | null };
62
+ func(name: string, returnType: AnyType, argTypes?: AnyType[], options?: FunctionOptions): CallableFunction & { errcheck: ErrcheckCallback | null };
138
63
  symbol(name: string): bigint;
139
64
  close(): void;
140
65
  readonly path: string;
@@ -158,7 +83,7 @@ export interface CallbackWrapper {
158
83
 
159
84
  /** Native Callback class */
160
85
  export class Callback {
161
- constructor(fn: Function, returnType: CTypeString | CType, argTypes?: (CTypeString | CType)[]);
86
+ constructor(fn: Function, returnType: AnyType, argTypes?: AnyType[]);
162
87
  readonly pointer: bigint;
163
88
  release(): void;
164
89
  }
@@ -173,7 +98,7 @@ export class ThreadSafeCallback extends Callback {}
173
98
  /** Field definition for struct */
174
99
  export interface FieldDef {
175
100
  name: string;
176
- type: CTypeString | CType | StructDef | ArrayTypeDef | BitFieldDef;
101
+ type: AnyType | StructDef | ArrayTypeDef | BitFieldDef;
177
102
  offset: number;
178
103
  size: number;
179
104
  alignment: number;
@@ -202,7 +127,7 @@ export interface StructDef {
202
127
  }
203
128
 
204
129
  // Helper types for improved typed structs
205
- export type FieldSpec = CTypeString | CType | StructDef | ArrayTypeDef | BitFieldDef | AnonymousField;
130
+ export type FieldSpec = AnyType | StructDef | ArrayTypeDef | BitFieldDef | AnonymousField;
206
131
 
207
132
  type JsFromCType<T> = T extends "int64" | "uint64" | "size_t"
208
133
  ? bigint
@@ -234,14 +159,14 @@ export interface UnionDef extends StructDef {
234
159
  /** Bit field definition */
235
160
  export interface BitFieldDef {
236
161
  readonly _isBitField: true;
237
- readonly baseType: CTypeString;
162
+ readonly baseType: AnyType;
238
163
  readonly bits: number;
239
164
  readonly baseSize: number;
240
165
  }
241
166
 
242
167
  /** Array type definition */
243
168
  export interface ArrayTypeDef {
244
- readonly elementType: CTypeString;
169
+ readonly elementType: AnyType;
245
170
  readonly length: number;
246
171
  readonly _isArrayType: true;
247
172
 
@@ -275,7 +200,7 @@ export interface AnonymousField {
275
200
 
276
201
  /** POINTER type definition */
277
202
  export interface PointerTypeDef {
278
- readonly _pointerTo: CTypeString | StructDef;
203
+ readonly _pointerTo: AnyType | StructDef;
279
204
  readonly _baseSize: number;
280
205
  readonly size: number;
281
206
 
@@ -293,7 +218,7 @@ export interface PointerTypeDef {
293
218
  /** Native StructType class */
294
219
  export class StructType {
295
220
  constructor(isUnion?: boolean);
296
- addField(name: string, type: CTypeString | CType | StructType | ArrayType): this;
221
+ addField(name: string, type: AnyType | StructType | ArrayType): this;
297
222
  getSize(): number;
298
223
  getAlignment(): number;
299
224
  create(values?: Record<string, any>): Buffer;
@@ -302,7 +227,7 @@ export class StructType {
302
227
 
303
228
  /** Native ArrayType class */
304
229
  export class ArrayType {
305
- constructor(elementType: CTypeString | CType, count: number);
230
+ constructor(elementType: AnyType, count: number);
306
231
  getSize(): number;
307
232
  getLength(): number;
308
233
  getAlignment(): number;
@@ -320,7 +245,7 @@ export class Structure<F extends Record<string, FieldSpec> = Record<string, any>
320
245
  static _pack_?: boolean;
321
246
  static _anonymous_?: string[];
322
247
  static create<ThisT extends Structure<F>>(this: new (...args: any[]) => ThisT, values?: Partial<FieldsToInstance<F>> | Buffer): ThisT;
323
- static toObject<ThisT extends Structure<F>>(this: new (...args: any[]) => ThisT, buf: Buffer | any): FieldsToInstance<F>;
248
+ static toObject<ThisT extends Structure<F>>(this: new (...args: any[]) => ThisT, bufOrInstance: Buffer | Structure<F>): FieldsToInstance<F>;
324
249
  _buffer: Buffer;
325
250
  _structDef: StructDef;
326
251
  get<K extends keyof F & string>(fieldName: K): FieldsToInstance<F>[K];
@@ -342,8 +267,8 @@ export class Union<F extends Record<string, FieldSpec> = Record<string, any>> ex
342
267
  export function load(path: string | null): Library;
343
268
 
344
269
  // Callbacks
345
- export function callback(fn: Function, returnType: CTypeString | CType, argTypes?: (CTypeString | CType)[]): CallbackWrapper;
346
- export function threadSafeCallback(fn: Function, returnType: CTypeString | CType, argTypes?: (CTypeString | CType)[]): CallbackWrapper;
270
+ export function callback(fn: Function, returnType: AnyType, argTypes?: AnyType[]): CallbackWrapper;
271
+ export function threadSafeCallback(fn: Function, returnType: AnyType, argTypes?: AnyType[]): CallbackWrapper;
347
272
 
348
273
  // Memory management - Python-compatible
349
274
  export function create_string_buffer(init: number | string | Buffer): Buffer;
@@ -355,24 +280,24 @@ export function memmove(dst: Buffer, src: Buffer | bigint, count: number): void;
355
280
  export function memset(dst: Buffer, value: number, count: number): void;
356
281
 
357
282
  // Memory - utility (no direct Python equivalent)
358
- export function readValue(ptr: Buffer | bigint | number, type: CTypeString | CType, offset?: number): any;
359
- export function writeValue(ptr: Buffer | bigint | number, type: CTypeString | CType, value: any, offset?: number): number;
360
- export function sizeof(type: CTypeString | CType | StructDef | ArrayTypeDef): number;
283
+ export function readValue(ptr: Buffer | bigint | number, type: AnyType, offset?: number): any;
284
+ export function writeValue(ptr: Buffer | bigint | number, type: AnyType, value: any, offset?: number): number | void;
285
+ export function sizeof(type: AnyType | StructDef | ArrayTypeDef): number;
361
286
  export function ptrToBuffer(address: bigint | number, size: number): Buffer;
362
287
 
363
288
  // Structures
364
- export function struct(fields: Record<string, CTypeString | CType | StructDef | ArrayTypeDef | BitFieldDef | AnonymousField>, options?: StructOptions): StructDef;
365
- export function union(fields: Record<string, CTypeString | CType | StructDef | ArrayTypeDef | BitFieldDef>): UnionDef;
289
+ export function struct(fields: Record<string, FieldSpec>, options?: StructOptions): StructDef;
290
+ export function union(fields: Record<string, FieldSpec>): UnionDef;
366
291
  // Factory helpers that return a typed class extending Structure/Union
367
292
  export function defineStruct<F extends Record<string, FieldSpec>>(fields: F, options?: StructOptions): new (...args: any[]) => Structure<F>;
368
293
  export function defineUnion<F extends Record<string, FieldSpec>>(fields: F): new (...args: any[]) => Union<F>;
369
- export function array(elementType: CTypeString, count: number): ArrayTypeDef;
370
- export function bitfield(baseType: CTypeString, bits: number): BitFieldDef;
294
+ export function array(elementType: AnyType | typeof Structure | typeof Union, count: number): ArrayTypeDef;
295
+ export function bitfield(baseType: AnyType, bits: number): BitFieldDef;
371
296
 
372
297
  // Pointers
373
- export function byref(obj: Buffer): Buffer;
374
- export function cast(ptr: Buffer | bigint, targetType: CTypeString | StructDef): any;
375
- export function POINTER(baseType: CTypeString | StructDef): PointerTypeDef;
298
+ export function byref(obj: Buffer | SimpleCDataInstance | { _buffer: Buffer }): Buffer;
299
+ export function cast(ptr: Buffer | bigint, targetType: AnyType | StructDef): Buffer | { [key: string]: any };
300
+ export function POINTER(baseType: AnyType | StructDef): PointerTypeDef;
376
301
 
377
302
  // Error handling
378
303
  export function get_errno(): number;
@@ -382,33 +307,55 @@ export function SetLastError(code: number): void;
382
307
  export function FormatError(code?: number): string;
383
308
  export function WinError(code?: number): Error & { winerror: number };
384
309
 
310
+ // =============================================================================
311
+ // SimpleCData - Base class for simple C data types
312
+ // =============================================================================
313
+
314
+ /** Base class for simple C data types (int, float, pointer, etc.) */
315
+ export interface SimpleCDataConstructor {
316
+ new (value?: any): SimpleCDataInstance;
317
+ readonly _size: number;
318
+ readonly _type: string;
319
+ readonly _isSimpleCData: true;
320
+ _reader(buf: Buffer, offset: number): any;
321
+ _writer(buf: Buffer, offset: number, value: any): void;
322
+ }
323
+
324
+ /** Instance of SimpleCData */
325
+ export interface SimpleCDataInstance {
326
+ value: any;
327
+ _buffer: Buffer;
328
+ toString(): string;
329
+ toJSON(): any;
330
+ valueOf(): any;
331
+ }
332
+
385
333
  // =============================================================================
386
334
  // Type Aliases (Python-compatible)
387
335
  // =============================================================================
388
336
 
389
- export const types: Types;
390
- export const c_void: CType;
391
- export const c_int: CType;
392
- export const c_uint: CType;
393
- export const c_int8: CType;
394
- export const c_uint8: CType;
395
- export const c_int16: CType;
396
- export const c_uint16: CType;
397
- export const c_int32: CType;
398
- export const c_uint32: CType;
399
- export const c_int64: CType;
400
- export const c_uint64: CType;
401
- export const c_float: CType;
402
- export const c_double: CType;
403
- export const c_char: CType;
404
- export const c_char_p: CType;
405
- export const c_wchar: CType;
406
- export const c_wchar_p: CType;
407
- export const c_void_p: CType;
408
- export const c_bool: CType;
409
- export const c_size_t: CType;
410
- export const c_long: CType;
411
- export const c_ulong: CType;
337
+ export const c_void: SimpleCDataConstructor;
338
+ export const c_int: SimpleCDataConstructor;
339
+ export const c_uint: SimpleCDataConstructor;
340
+ export const c_int8: SimpleCDataConstructor;
341
+ export const c_uint8: SimpleCDataConstructor;
342
+ export const c_int16: SimpleCDataConstructor;
343
+ export const c_uint16: SimpleCDataConstructor;
344
+ export const c_int32: SimpleCDataConstructor;
345
+ export const c_uint32: SimpleCDataConstructor;
346
+ export const c_int64: SimpleCDataConstructor;
347
+ export const c_uint64: SimpleCDataConstructor;
348
+ export const c_float: SimpleCDataConstructor;
349
+ export const c_double: SimpleCDataConstructor;
350
+ export const c_char: SimpleCDataConstructor;
351
+ export const c_char_p: SimpleCDataConstructor;
352
+ export const c_wchar: SimpleCDataConstructor;
353
+ export const c_wchar_p: SimpleCDataConstructor;
354
+ export const c_void_p: SimpleCDataConstructor;
355
+ export const c_bool: SimpleCDataConstructor;
356
+ export const c_size_t: SimpleCDataConstructor;
357
+ export const c_long: SimpleCDataConstructor;
358
+ export const c_ulong: SimpleCDataConstructor;
412
359
 
413
360
  // =============================================================================
414
361
  // Constants