node-ctypes 1.2.0 → 1.4.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.
package/README.md CHANGED
@@ -221,15 +221,15 @@ console.log(u.f); // 42 reinterpreted as float
221
221
  ### Bit Fields - Compact Data Structures
222
222
 
223
223
  ```javascript
224
- import { Structure, bitfield, c_uint32 } from 'node-ctypes';
224
+ import { Structure, c_uint32 } from 'node-ctypes';
225
225
 
226
- // Bit fields for flags and compact data
226
+ // Bit fields using Python-style syntax: [name, type, bits]
227
227
  class Flags extends Structure {
228
228
  static _fields_ = [
229
- ["enabled", bitfield(c_uint32, 1)], // 1 bit
230
- ["mode", bitfield(c_uint32, 3)], // 3 bits
231
- ["priority", bitfield(c_uint32, 4)], // 4 bits
232
- ["reserved", bitfield(c_uint32, 24)] // 24 bits
229
+ ["enabled", c_uint32, 1], // 1 bit
230
+ ["mode", c_uint32, 3], // 3 bits
231
+ ["priority", c_uint32, 4], // 4 bits
232
+ ["reserved", c_uint32, 24] // 24 bits
233
233
  ];
234
234
  }
235
235
 
@@ -244,6 +244,19 @@ console.log(flags.mode); // 5
244
244
  console.log(flags.priority); // 12
245
245
  ```
246
246
 
247
+ **Alternative syntax with `bitfield()` helper:**
248
+
249
+ ```javascript
250
+ import { Structure, bitfield, c_uint32 } from 'node-ctypes';
251
+
252
+ class Flags extends Structure {
253
+ static _fields_ = [
254
+ ["enabled", bitfield(c_uint32, 1)],
255
+ ["mode", bitfield(c_uint32, 3)],
256
+ ];
257
+ }
258
+ ```
259
+
247
260
  ### Arrays - Fixed-size and Dynamic
248
261
 
249
262
  ```javascript
@@ -508,9 +521,33 @@ Benchmarked on Windows with Node.js v24.11.0:
508
521
  **Key Insights:**
509
522
  - koffi excels at simple operations and struct access
510
523
  - node-ctypes competitive on complex argument handling
511
- - **Struct performance gap**: koffi 15x faster due to direct object manipulation
524
+ - **Struct performance gap**: koffi ~13x faster due to plain object vs Proxy+N-API
525
+ - **Workaround**: Use `toObject()` for repeated struct reads (see below)
512
526
  - **Callback overhead**: koffi 1.5x faster at callback creation
513
527
 
528
+ ### Struct Performance Tip
529
+
530
+ When reading struct fields repeatedly (e.g., in a tight loop), use `toObject()` to convert to a plain JavaScript object:
531
+
532
+ ```javascript
533
+ const point = Point.create({ x: 10, y: 20 });
534
+
535
+ // ❌ Slow: Each access goes through Proxy → N-API → buffer read
536
+ for (let i = 0; i < 1000000; i++) {
537
+ const x = point.x; // ~80ns per access
538
+ }
539
+
540
+ // ✅ Fast: Convert once, then use plain object access
541
+ const obj = point.toObject(); // { x: 10, y: 20 }
542
+ for (let i = 0; i < 1000000; i++) {
543
+ const x = obj.x; // ~6ns per access (same as koffi!)
544
+ }
545
+ ```
546
+
547
+ **When to use direct access vs toObject():**
548
+ - **Direct access (`point.x`)**: Always synchronized with underlying buffer; required when C code modifies the buffer
549
+ - **`toObject()`**: Snapshot copy; use for read-only loops or when passing data to JS-only code
550
+
514
551
  **Transparent API overhead**: Only **3.5%** for auto `._buffer` extraction!
515
552
 
516
553
  *See `tests/benchmarks/` for full benchmark suite.*
@@ -623,7 +660,8 @@ puts(s);
623
660
 
624
661
  **Types and helpers**
625
662
  - `sizeof(type)` → `number` : size in bytes of a type.
626
- - `POINTER(baseType)` : creates a pointer type with helpers `create()`, `fromBuffer()`, `deref()`, `set()`.
663
+ - `POINTER(baseType)` : creates a pointer type factory (see [POINTER and pointer() API](#pointer-and-pointer-api) below).
664
+ - `pointer(obj)` : creates a pointer to an existing ctypes instance (Python-compatible).
627
665
  - `byref(buffer)` : passes a buffer by reference (Python ctypes compatibility).
628
666
  - `cast(ptr, targetType)` : interprets a pointer as another type (returns wrapper for struct).
629
667
 
@@ -700,6 +738,82 @@ Write a value to memory.
700
738
  #### `sizeof(type)` → `number`
701
739
  Get the size of a type in bytes.
702
740
 
741
+ #### POINTER and pointer() API
742
+
743
+ `node-ctypes` provides a Python ctypes-compatible pointer API:
744
+
745
+ ```javascript
746
+ import { POINTER, pointer, c_int32, Structure } from 'node-ctypes';
747
+
748
+ // Create a pointer type
749
+ const IntPtr = POINTER(c_int32);
750
+
751
+ // Create NULL pointer
752
+ const p1 = IntPtr.create();
753
+ console.log(p1.isNull); // true
754
+
755
+ // Create pointer from buffer
756
+ const buf = Buffer.alloc(12);
757
+ buf.writeInt32LE(10, 0);
758
+ buf.writeInt32LE(20, 4);
759
+ buf.writeInt32LE(30, 8);
760
+
761
+ const p2 = IntPtr.fromBuffer(buf);
762
+
763
+ // .contents property (Python-compatible)
764
+ console.log(p2.contents); // 10
765
+ p2.contents = 100;
766
+ console.log(buf.readInt32LE(0)); // 100
767
+
768
+ // Pointer indexing (Python-compatible)
769
+ console.log(p2[0]); // 100
770
+ console.log(p2[1]); // 20
771
+ console.log(p2[2]); // 30
772
+
773
+ p2[1] = 200;
774
+ console.log(buf.readInt32LE(4)); // 200
775
+
776
+ // pointer() function - create pointer to existing object
777
+ const x = new c_int32(42);
778
+ const px = pointer(x);
779
+ console.log(px.contents); // 42
780
+ px.contents = 100;
781
+ console.log(x.value); // 100
782
+
783
+ // Works with structures too
784
+ class Point extends Structure {
785
+ static _fields_ = [["x", c_int32], ["y", c_int32]];
786
+ }
787
+ const pt = new Point({ x: 10, y: 20 });
788
+ const ppt = pointer(pt);
789
+ ```
790
+
791
+ **POINTER type methods:**
792
+ - `POINTER(baseType)` - creates a pointer type factory
793
+ - `PointerType.create()` - creates a NULL pointer instance
794
+ - `PointerType.fromBuffer(buf)` - creates pointer to buffer
795
+ - `PointerType.fromAddress(addr)` - creates pointer from address
796
+
797
+ **Pointer instance properties:**
798
+ - `.contents` - get/set dereferenced value (Python-compatible)
799
+ - `.address` - get raw address as BigInt
800
+ - `.isNull` - check if pointer is NULL
801
+ - `[n]` - array-style indexing with pointer arithmetic
802
+ - `.deref()` - alias for `.contents` getter
803
+ - `.set(value)` - update pointer target
804
+
805
+ **Using POINTER in function definitions:**
806
+ ```javascript
807
+ // POINTER types can be used as argtypes and restype
808
+ const IntPtr = POINTER(c_int32);
809
+
810
+ // As argument type
811
+ const memset = msvcrt.func("memset", c_void_p, [IntPtr, c_int32, c_size_t]);
812
+
813
+ // As return type
814
+ const memchr = msvcrt.func("memchr", IntPtr, [c_void_p, c_int32, c_size_t]);
815
+ ```
816
+
703
817
  #### `struct(fields)` → `StructDefinition`
704
818
  Create a simple struct definition.
705
819
 
@@ -720,10 +834,11 @@ Base class for Python-like union definitions. Subclasses should define `static _
720
834
  | **Structs** | `class Point(Structure):`<br>&nbsp;&nbsp;`_fields_ = [("x", c_int)]` | `class Point extends Structure`<br>&nbsp;&nbsp;`{ static _fields_ = [["x", c_int]] }` |
721
835
  | **Unions** | `class U(Union):`<br>&nbsp;&nbsp;`_fields_ = [("i", c_int)]` | `class U extends Union`<br>&nbsp;&nbsp;`{ static _fields_ = [["i", c_int]] }` |
722
836
  | **Arrays** | `c_int * 5` | `array(c_int, 5)` |
723
- | **Bit fields** | `("flags", c_uint, 3)` | `bitfield(c_uint32, 3)` |
837
+ | **Bit fields** | `("flags", c_uint, 3)` | `["flags", c_uint32, 3]`<br>**or** `bitfield(c_uint32, 3)` |
724
838
  | **Callbacks** | `CFUNCTYPE(c_int, c_int)` | `callback(fn, c_int, [c_int])` |
725
839
  | **Strings** | `c_char_p(b"hello")` | `create_string_buffer("hello")`<br>**or**<br>`new c_char_p(b"hello")` |
726
- | **Pointers** | `POINTER(c_int)` | `c_void_p` |
840
+ | **Pointers** | `POINTER(c_int)`<br>`p.contents`<br>`p[0]` | `POINTER(c_int)`<br>`p.contents`<br>`p[0]` |
841
+ | **pointer()** | `pointer(obj)` | `pointer(obj)` |
727
842
  | **Variadic** | `sprintf(buf, b"%d", 42)` | `sprintf(buf, fmt, 42)` (auto) |
728
843
  | **Sizeof** | `sizeof(c_int)` | `sizeof(c_int)` |
729
844
 
Binary file
Binary file