node-ctypes 1.2.0 → 1.3.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 +125 -10
- package/build/Release/ctypes-darwin-arm64.node +0 -0
- package/build/Release/ctypes-darwin-x64.node +0 -0
- package/build/Release/ctypes-linux-arm64.node +0 -0
- package/build/Release/ctypes-linux-x64.node +0 -0
- package/build/Release/ctypes-win32-arm64.node +0 -0
- package/build/Release/ctypes-win32-x64.node +0 -0
- package/lib/core/Library.js +222 -214
- package/lib/core/types.js +7 -0
- package/lib/index.d.ts +23 -1
- package/lib/index.js +56 -59
- package/lib/memory/pointer.js +243 -25
- package/lib/structures/Structure.js +261 -230
- package/lib/structures/Union.js +10 -2
- package/lib/structures/helpers/common.js +9 -1
- package/lib/structures/helpers/struct.js +6 -1
- package/lib/structures/helpers/union.js +9 -19
- package/lib/types/primitives.js +1 -1
- package/package.json +1 -1
package/lib/core/types.js
CHANGED
|
@@ -88,6 +88,13 @@ export function _toNativeType(type, native) {
|
|
|
88
88
|
return type._type;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
// POINTER types: return CType.POINTER (11)
|
|
92
|
+
// POINTER(baseType) returns an object with _pointerTo property
|
|
93
|
+
if (type && typeof type === "object" && type._pointerTo !== undefined) {
|
|
94
|
+
// All pointer types are passed as generic pointers to FFI
|
|
95
|
+
return native.CType.POINTER;
|
|
96
|
+
}
|
|
97
|
+
|
|
91
98
|
// Structure/Union classes: pass through unchanged
|
|
92
99
|
// These are handled specially by the FFI layer
|
|
93
100
|
if (typeof type === "function" && type.prototype) {
|
package/lib/index.d.ts
CHANGED
|
@@ -92,6 +92,16 @@ export class CDLL {
|
|
|
92
92
|
close(): void;
|
|
93
93
|
readonly path: string;
|
|
94
94
|
readonly loaded: boolean;
|
|
95
|
+
/** Python-like function access: lib.FuncName returns a FunctionWrapper */
|
|
96
|
+
[funcName: string]: FunctionWrapper | any;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** FunctionWrapper for Python-like argtypes/restype syntax */
|
|
100
|
+
export interface FunctionWrapper {
|
|
101
|
+
(...args: any[]): any;
|
|
102
|
+
argtypes: AnyType[];
|
|
103
|
+
restype: AnyType;
|
|
104
|
+
errcheck: ErrcheckCallback | null;
|
|
95
105
|
}
|
|
96
106
|
|
|
97
107
|
/** WinDLL - stdcall calling convention library (Windows) */
|
|
@@ -326,6 +336,7 @@ export function bitfield(baseType: AnyType, bits: number): BitFieldDef;
|
|
|
326
336
|
export function byref(obj: Buffer | SimpleCDataInstance | { _buffer: Buffer }): Buffer;
|
|
327
337
|
export function cast(ptr: Buffer | bigint, targetType: AnyType | StructDef): Buffer | { [key: string]: any };
|
|
328
338
|
export function POINTER(baseType: AnyType | StructDef): PointerTypeDef;
|
|
339
|
+
export function pointer(obj: SimpleCDataInstance | { _buffer: Buffer }): SimpleCDataInstance & { contents: any; [index: number]: any };
|
|
329
340
|
|
|
330
341
|
// Error handling
|
|
331
342
|
export function get_errno(): number;
|
|
@@ -343,7 +354,7 @@ export function WinError(code?: number): Error & { winerror: number };
|
|
|
343
354
|
export interface SimpleCDataConstructor {
|
|
344
355
|
new (value?: any): SimpleCDataInstance;
|
|
345
356
|
readonly _size: number;
|
|
346
|
-
readonly _type: number;
|
|
357
|
+
readonly _type: number; // CType numeric value from native module
|
|
347
358
|
readonly _isSimpleCData: true;
|
|
348
359
|
_reader(buf: Buffer, offset: number): any;
|
|
349
360
|
_writer(buf: Buffer, offset: number, value: any): void;
|
|
@@ -385,6 +396,17 @@ export const c_size_t: SimpleCDataConstructor;
|
|
|
385
396
|
export const c_long: SimpleCDataConstructor;
|
|
386
397
|
export const c_ulong: SimpleCDataConstructor;
|
|
387
398
|
|
|
399
|
+
// Python-compatible aliases
|
|
400
|
+
export const c_byte: SimpleCDataConstructor;
|
|
401
|
+
export const c_ubyte: SimpleCDataConstructor;
|
|
402
|
+
export const c_short: SimpleCDataConstructor;
|
|
403
|
+
export const c_ushort: SimpleCDataConstructor;
|
|
404
|
+
export const c_longlong: SimpleCDataConstructor;
|
|
405
|
+
export const c_ulonglong: SimpleCDataConstructor;
|
|
406
|
+
|
|
407
|
+
/** SimpleCData base class for creating custom simple types */
|
|
408
|
+
export const SimpleCData: SimpleCDataConstructor;
|
|
409
|
+
|
|
388
410
|
// =============================================================================
|
|
389
411
|
// Constants
|
|
390
412
|
// =============================================================================
|
package/lib/index.js
CHANGED
|
@@ -35,39 +35,12 @@ import {
|
|
|
35
35
|
memmove as _memmove,
|
|
36
36
|
memset as _memset,
|
|
37
37
|
} from "./memory/buffer.js";
|
|
38
|
-
import {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
} from "./memory/operations.js";
|
|
43
|
-
import {
|
|
44
|
-
addressOf as _addressOf,
|
|
45
|
-
byref as _byref,
|
|
46
|
-
cast as _cast,
|
|
47
|
-
ptrToBuffer as _ptrToBuffer,
|
|
48
|
-
POINTER as _POINTER,
|
|
49
|
-
} from "./memory/pointer.js";
|
|
50
|
-
import {
|
|
51
|
-
get_errno as _get_errno,
|
|
52
|
-
set_errno as _set_errno,
|
|
53
|
-
GetLastError as _GetLastError,
|
|
54
|
-
SetLastError as _SetLastError,
|
|
55
|
-
FormatError as _FormatError,
|
|
56
|
-
WinError as _WinError,
|
|
57
|
-
} from "./platform/errors.js";
|
|
58
|
-
import {
|
|
59
|
-
bitfield as _bitfield,
|
|
60
|
-
_isStruct,
|
|
61
|
-
_isArrayType,
|
|
62
|
-
_isBitField,
|
|
63
|
-
} from "./structures/helpers/common.js";
|
|
38
|
+
import { readValue as _readValue, writeValue as _writeValue, sizeof as _sizeof } from "./memory/operations.js";
|
|
39
|
+
import { addressOf as _addressOf, byref as _byref, cast as _cast, ptrToBuffer as _ptrToBuffer, POINTER as _POINTER, pointer as _pointer } from "./memory/pointer.js";
|
|
40
|
+
import { get_errno as _get_errno, set_errno as _set_errno, GetLastError as _GetLastError, SetLastError as _SetLastError, FormatError as _FormatError, WinError as _WinError } from "./platform/errors.js";
|
|
41
|
+
import { bitfield as _bitfield, _isStruct, _isArrayType, _isBitField } from "./structures/helpers/common.js";
|
|
64
42
|
import { array as _array } from "./structures/helpers/array.js";
|
|
65
|
-
import {
|
|
66
|
-
_readBitField as _readBitFieldHelper,
|
|
67
|
-
_writeBitField as _writeBitFieldHelper,
|
|
68
|
-
_readUintFromBuffer,
|
|
69
|
-
_writeUintToBuffer,
|
|
70
|
-
} from "./structures/helpers/bitfield.js";
|
|
43
|
+
import { _readBitField as _readBitFieldHelper, _writeBitField as _writeBitFieldHelper, _readUintFromBuffer, _writeUintToBuffer } from "./structures/helpers/bitfield.js";
|
|
71
44
|
import { union as _union } from "./structures/helpers/union.js";
|
|
72
45
|
import { struct as _struct } from "./structures/helpers/struct.js";
|
|
73
46
|
import { createStructureClass } from "./structures/Structure.js";
|
|
@@ -163,13 +136,7 @@ function load(libPath) {
|
|
|
163
136
|
* Wrapper per funzioni con sintassi Python-like ctypes (argtypes/restype)
|
|
164
137
|
*/
|
|
165
138
|
// Create Library classes (FunctionWrapper, CDLL, WinDLL)
|
|
166
|
-
const { FunctionWrapper, CDLL, WinDLL } = createLibraryClasses(
|
|
167
|
-
Library,
|
|
168
|
-
LRUCache,
|
|
169
|
-
_toNativeType,
|
|
170
|
-
_toNativeTypes,
|
|
171
|
-
native
|
|
172
|
-
);
|
|
139
|
+
const { FunctionWrapper, CDLL, WinDLL } = createLibraryClasses(Library, LRUCache, _toNativeType, _toNativeTypes, native);
|
|
173
140
|
|
|
174
141
|
// ============================================================================
|
|
175
142
|
// Callback Functions
|
|
@@ -260,6 +227,26 @@ function POINTER(baseType) {
|
|
|
260
227
|
return _POINTER(baseType, sizeof, alloc, readValue, writeValue, c_void_p, native);
|
|
261
228
|
}
|
|
262
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Creates a pointer to an existing ctypes object.
|
|
232
|
+
* Python ctypes compatible: pointer(obj) returns a pointer to obj.
|
|
233
|
+
*
|
|
234
|
+
* @param {Object} obj - Object to create pointer to (must have ._buffer or be a Buffer)
|
|
235
|
+
* @returns {Object} Pointer instance pointing to obj
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```javascript
|
|
239
|
+
* const x = new c_int32(42);
|
|
240
|
+
* const p = pointer(x);
|
|
241
|
+
* console.log(p.contents); // 42
|
|
242
|
+
* p.contents = 100;
|
|
243
|
+
* console.log(x.value); // 100
|
|
244
|
+
* ```
|
|
245
|
+
*/
|
|
246
|
+
function pointer(obj) {
|
|
247
|
+
return _pointer(obj, _POINTER, sizeof, alloc, readValue, writeValue, c_void_p, native);
|
|
248
|
+
}
|
|
249
|
+
|
|
263
250
|
/**
|
|
264
251
|
* Helper per definire union (tutti i campi condividono offset 0)
|
|
265
252
|
* Supporta nested structs e bitfields come struct()
|
|
@@ -304,9 +291,8 @@ function defineUnion(fields) {
|
|
|
304
291
|
// --------------------------------------------------------------------------
|
|
305
292
|
|
|
306
293
|
// Create Structure and Union classes with injected dependencies
|
|
307
|
-
const Structure = createStructureClass(alloc, struct);
|
|
308
|
-
const Union = createUnionClass(Structure, union);
|
|
309
|
-
|
|
294
|
+
const Structure = createStructureClass(alloc, struct, bitfield);
|
|
295
|
+
const Union = createUnionClass(Structure, union, bitfield);
|
|
310
296
|
|
|
311
297
|
/**
|
|
312
298
|
* Helper per creare array a dimensione fissa (come c_int * 5 in Python)
|
|
@@ -412,28 +398,38 @@ function struct(fields, options = {}) {
|
|
|
412
398
|
const SimpleCData = createSimpleCDataClass(alloc);
|
|
413
399
|
|
|
414
400
|
// Create all primitive type classes
|
|
415
|
-
const primitiveTypes = createPrimitiveTypes(
|
|
416
|
-
SimpleCData,
|
|
417
|
-
native,
|
|
418
|
-
addressOf,
|
|
419
|
-
cstring,
|
|
420
|
-
wstring,
|
|
421
|
-
readCString,
|
|
422
|
-
readWString
|
|
423
|
-
);
|
|
401
|
+
const primitiveTypes = createPrimitiveTypes(SimpleCData, native, addressOf, cstring, wstring, readCString, readWString);
|
|
424
402
|
|
|
425
403
|
// Destructure all types for easy access
|
|
426
404
|
const {
|
|
427
405
|
c_void,
|
|
428
|
-
c_int8,
|
|
429
|
-
|
|
430
|
-
|
|
406
|
+
c_int8,
|
|
407
|
+
c_int16,
|
|
408
|
+
c_int32,
|
|
409
|
+
c_int64,
|
|
410
|
+
c_uint8,
|
|
411
|
+
c_uint16,
|
|
412
|
+
c_uint32,
|
|
413
|
+
c_uint64,
|
|
414
|
+
c_float,
|
|
415
|
+
c_double,
|
|
431
416
|
c_bool,
|
|
432
|
-
c_char,
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
417
|
+
c_char,
|
|
418
|
+
c_wchar,
|
|
419
|
+
c_void_p,
|
|
420
|
+
c_char_p,
|
|
421
|
+
c_wchar_p,
|
|
422
|
+
c_size_t,
|
|
423
|
+
c_long,
|
|
424
|
+
c_ulong,
|
|
425
|
+
c_byte,
|
|
426
|
+
c_ubyte,
|
|
427
|
+
c_short,
|
|
428
|
+
c_ushort,
|
|
429
|
+
c_int,
|
|
430
|
+
c_uint,
|
|
431
|
+
c_longlong,
|
|
432
|
+
c_ulonglong,
|
|
437
433
|
} = primitiveTypes;
|
|
438
434
|
|
|
439
435
|
// ============================================================================
|
|
@@ -523,6 +519,7 @@ export {
|
|
|
523
519
|
byref,
|
|
524
520
|
cast,
|
|
525
521
|
POINTER,
|
|
522
|
+
pointer,
|
|
526
523
|
|
|
527
524
|
// Error handling
|
|
528
525
|
get_errno,
|
package/lib/memory/pointer.js
CHANGED
|
@@ -289,54 +289,225 @@ export function POINTER(baseType, sizeof, alloc, readValue, writeValue, c_void_p
|
|
|
289
289
|
const baseSize = typeof baseType === "object" ? baseType.size : sizeof(baseType);
|
|
290
290
|
const typeName = typeof baseType === "object" ? "struct" : baseType._type || "unknown";
|
|
291
291
|
|
|
292
|
-
|
|
292
|
+
/**
|
|
293
|
+
* Helper to get buffer's memory address using native writeValue
|
|
294
|
+
*/
|
|
295
|
+
function getBufferAddress(buf) {
|
|
296
|
+
const tempBuf = alloc(native.POINTER_SIZE);
|
|
297
|
+
native.writeValue(tempBuf, native.CType.POINTER, buf, 0);
|
|
298
|
+
if (native.POINTER_SIZE === 8) return tempBuf.readBigUInt64LE(0);
|
|
299
|
+
return BigInt(tempBuf.readUInt32LE(0));
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Creates a pointer instance with Python ctypes-compatible API.
|
|
304
|
+
* Supports .contents property and [index] access for pointer arithmetic.
|
|
305
|
+
*/
|
|
306
|
+
function createPointerInstance(addressOrBuffer) {
|
|
307
|
+
let _address = 0n;
|
|
308
|
+
let _buffer = null;
|
|
309
|
+
|
|
310
|
+
if (addressOrBuffer === undefined || addressOrBuffer === null) {
|
|
311
|
+
_address = 0n;
|
|
312
|
+
} else if (typeof addressOrBuffer === "bigint") {
|
|
313
|
+
_address = addressOrBuffer;
|
|
314
|
+
} else if (typeof addressOrBuffer === "number") {
|
|
315
|
+
_address = BigInt(addressOrBuffer);
|
|
316
|
+
} else if (Buffer.isBuffer(addressOrBuffer)) {
|
|
317
|
+
// This is a buffer we're pointing TO
|
|
318
|
+
_buffer = addressOrBuffer;
|
|
319
|
+
_address = getBufferAddress(addressOrBuffer);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const instance = {
|
|
323
|
+
_pointerType: PointerType,
|
|
324
|
+
_baseType: baseType,
|
|
325
|
+
_baseSize: baseSize,
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Get the raw address as BigInt
|
|
329
|
+
*/
|
|
330
|
+
get address() {
|
|
331
|
+
return _address;
|
|
332
|
+
},
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Python ctypes compatible: get/set the value at the pointed location.
|
|
336
|
+
* In Python: p.contents returns the dereferenced value.
|
|
337
|
+
*/
|
|
338
|
+
get contents() {
|
|
339
|
+
if (_address === 0n && !_buffer) {
|
|
340
|
+
throw new Error("NULL pointer access");
|
|
341
|
+
}
|
|
342
|
+
if (_buffer) {
|
|
343
|
+
// We have the actual buffer, read from it
|
|
344
|
+
return readValue(_buffer, baseType, 0);
|
|
345
|
+
}
|
|
346
|
+
// We only have address - need native support to read
|
|
347
|
+
const buf = native.ptrToBuffer(_address, baseSize);
|
|
348
|
+
return readValue(buf, baseType, 0);
|
|
349
|
+
},
|
|
350
|
+
|
|
351
|
+
set contents(value) {
|
|
352
|
+
if (_address === 0n && !_buffer) {
|
|
353
|
+
throw new Error("NULL pointer access");
|
|
354
|
+
}
|
|
355
|
+
if (_buffer) {
|
|
356
|
+
writeValue(_buffer, baseType, value, 0);
|
|
357
|
+
} else {
|
|
358
|
+
const buf = native.ptrToBuffer(_address, baseSize);
|
|
359
|
+
writeValue(buf, baseType, value, 0);
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Returns the buffer this pointer points to (if available)
|
|
365
|
+
*/
|
|
366
|
+
get _buffer() {
|
|
367
|
+
return _buffer;
|
|
368
|
+
},
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Dereference - alias for contents getter
|
|
372
|
+
*/
|
|
373
|
+
deref() {
|
|
374
|
+
return this.contents;
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Set pointer to point to a new address/buffer
|
|
379
|
+
*/
|
|
380
|
+
set(value) {
|
|
381
|
+
if (Buffer.isBuffer(value)) {
|
|
382
|
+
_buffer = value;
|
|
383
|
+
_address = getBufferAddress(value);
|
|
384
|
+
} else if (typeof value === "bigint") {
|
|
385
|
+
_address = value;
|
|
386
|
+
_buffer = null;
|
|
387
|
+
} else if (typeof value === "number") {
|
|
388
|
+
_address = BigInt(value);
|
|
389
|
+
_buffer = null;
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Check if pointer is NULL
|
|
395
|
+
*/
|
|
396
|
+
get isNull() {
|
|
397
|
+
return _address === 0n && !_buffer;
|
|
398
|
+
},
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* For compatibility - get pointer as buffer (8 bytes containing address)
|
|
402
|
+
*/
|
|
403
|
+
toBuffer() {
|
|
404
|
+
const buf = alloc(native.POINTER_SIZE);
|
|
405
|
+
writeValue(buf, c_void_p, _address);
|
|
406
|
+
return buf;
|
|
407
|
+
},
|
|
408
|
+
|
|
409
|
+
toString() {
|
|
410
|
+
return `<${typeName} pointer at 0x${_address.toString(16)}>`;
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// Use Proxy for [index] access (pointer arithmetic)
|
|
415
|
+
return new Proxy(instance, {
|
|
416
|
+
get(target, prop, receiver) {
|
|
417
|
+
// Numeric index access: p[0], p[1], etc.
|
|
418
|
+
if (typeof prop === "string" && /^\d+$/.test(prop)) {
|
|
419
|
+
const index = parseInt(prop, 10);
|
|
420
|
+
if (target.isNull) {
|
|
421
|
+
throw new Error("NULL pointer access");
|
|
422
|
+
}
|
|
423
|
+
const offset = index * baseSize;
|
|
424
|
+
if (_buffer && offset + baseSize <= _buffer.length) {
|
|
425
|
+
return readValue(_buffer, baseType, offset);
|
|
426
|
+
}
|
|
427
|
+
// Use native to read at address + offset
|
|
428
|
+
const addr = _address + BigInt(offset);
|
|
429
|
+
const buf = native.ptrToBuffer(addr, baseSize);
|
|
430
|
+
return readValue(buf, baseType, 0);
|
|
431
|
+
}
|
|
432
|
+
return Reflect.get(target, prop, receiver);
|
|
433
|
+
},
|
|
434
|
+
|
|
435
|
+
set(target, prop, value, receiver) {
|
|
436
|
+
// Numeric index access: p[0] = value, p[1] = value, etc.
|
|
437
|
+
if (typeof prop === "string" && /^\d+$/.test(prop)) {
|
|
438
|
+
const index = parseInt(prop, 10);
|
|
439
|
+
if (target.isNull) {
|
|
440
|
+
throw new Error("NULL pointer access");
|
|
441
|
+
}
|
|
442
|
+
const offset = index * baseSize;
|
|
443
|
+
if (_buffer && offset + baseSize <= _buffer.length) {
|
|
444
|
+
writeValue(_buffer, baseType, value, offset);
|
|
445
|
+
return true;
|
|
446
|
+
}
|
|
447
|
+
// Use native to write at address + offset
|
|
448
|
+
const addr = _address + BigInt(offset);
|
|
449
|
+
const buf = native.ptrToBuffer(addr, baseSize);
|
|
450
|
+
writeValue(buf, baseType, value, 0);
|
|
451
|
+
return true;
|
|
452
|
+
}
|
|
453
|
+
return Reflect.set(target, prop, value, receiver);
|
|
454
|
+
},
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Pointer type factory - creates pointer instances
|
|
460
|
+
*/
|
|
461
|
+
const PointerType = {
|
|
293
462
|
_pointerTo: baseType,
|
|
294
463
|
_baseSize: baseSize,
|
|
295
464
|
size: native.POINTER_SIZE,
|
|
296
465
|
|
|
297
466
|
/**
|
|
298
|
-
* Creates a
|
|
299
|
-
* @
|
|
467
|
+
* Creates a new pointer instance.
|
|
468
|
+
* @param {Buffer|bigint|number} [value] - Initial value (buffer to point to, or address)
|
|
469
|
+
* @returns {Object} Pointer instance with .contents and [index] access
|
|
300
470
|
*/
|
|
301
|
-
create() {
|
|
302
|
-
|
|
303
|
-
writeValue(buf, c_void_p, 0n);
|
|
304
|
-
return buf;
|
|
471
|
+
create(value) {
|
|
472
|
+
return createPointerInstance(value);
|
|
305
473
|
},
|
|
306
474
|
|
|
307
475
|
/**
|
|
308
|
-
* Creates a pointer
|
|
309
|
-
* @param {Buffer} targetBuf -
|
|
310
|
-
* @returns {
|
|
476
|
+
* Creates a pointer from an existing buffer (points to that buffer).
|
|
477
|
+
* @param {Buffer} targetBuf - Buffer to point to
|
|
478
|
+
* @returns {Object} Pointer instance
|
|
311
479
|
*/
|
|
312
480
|
fromBuffer(targetBuf) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
481
|
+
return createPointerInstance(targetBuf);
|
|
482
|
+
},
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Creates a pointer from a raw address.
|
|
486
|
+
* @param {bigint|number} address - Memory address
|
|
487
|
+
* @returns {Object} Pointer instance
|
|
488
|
+
*/
|
|
489
|
+
fromAddress(address) {
|
|
490
|
+
return createPointerInstance(typeof address === "bigint" ? address : BigInt(address));
|
|
316
491
|
},
|
|
317
492
|
|
|
318
493
|
/**
|
|
319
|
-
* Dereferences
|
|
320
|
-
* @
|
|
321
|
-
* @returns {bigint|null} Address value, or null if NULL pointer
|
|
494
|
+
* Legacy API: Dereferences a pointer buffer.
|
|
495
|
+
* @deprecated Use pointer instance .contents instead
|
|
322
496
|
*/
|
|
323
497
|
deref(ptrBuf) {
|
|
324
498
|
const addr = readValue(ptrBuf, c_void_p);
|
|
325
499
|
if (addr === 0n || addr === null) {
|
|
326
500
|
return null;
|
|
327
501
|
}
|
|
328
|
-
// For struct types, return address (can't safely create buffer without native support)
|
|
329
502
|
if (typeof baseType === "object" && baseType.toObject) {
|
|
330
503
|
return addr;
|
|
331
504
|
}
|
|
332
|
-
// For primitive types, return address
|
|
333
505
|
return addr;
|
|
334
506
|
},
|
|
335
507
|
|
|
336
508
|
/**
|
|
337
|
-
* Sets
|
|
338
|
-
* @
|
|
339
|
-
* @param {Buffer|bigint|number} value - Value to set (buffer or address)
|
|
509
|
+
* Legacy API: Sets pointer buffer value.
|
|
510
|
+
* @deprecated Use pointer instance .set() instead
|
|
340
511
|
*/
|
|
341
512
|
set(ptrBuf, value) {
|
|
342
513
|
if (Buffer.isBuffer(value)) {
|
|
@@ -346,12 +517,59 @@ export function POINTER(baseType, sizeof, alloc, readValue, writeValue, c_void_p
|
|
|
346
517
|
}
|
|
347
518
|
},
|
|
348
519
|
|
|
349
|
-
/**
|
|
350
|
-
* Returns string representation of pointer type.
|
|
351
|
-
* @returns {string} Type name
|
|
352
|
-
*/
|
|
353
520
|
toString() {
|
|
354
521
|
return `POINTER(${typeName})`;
|
|
355
522
|
},
|
|
356
523
|
};
|
|
524
|
+
|
|
525
|
+
return PointerType;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Creates a pointer to an existing ctypes object.
|
|
530
|
+
* Python ctypes compatible: pointer(obj) returns a pointer to obj.
|
|
531
|
+
*
|
|
532
|
+
* @param {Object} obj - Object to create pointer to (must have ._buffer or be a Buffer)
|
|
533
|
+
* @param {Function} POINTER_fn - POINTER function reference
|
|
534
|
+
* @param {Function} sizeof - sizeof function reference
|
|
535
|
+
* @param {Function} alloc - alloc function reference
|
|
536
|
+
* @param {Function} readValue - readValue function reference
|
|
537
|
+
* @param {Function} writeValue - writeValue function reference
|
|
538
|
+
* @param {Function} c_void_p - c_void_p type reference
|
|
539
|
+
* @param {Object} native - Native module reference
|
|
540
|
+
* @returns {Object} Pointer instance pointing to obj
|
|
541
|
+
*
|
|
542
|
+
* @example
|
|
543
|
+
* ```javascript
|
|
544
|
+
* const x = new c_int32(42);
|
|
545
|
+
* const p = pointer(x);
|
|
546
|
+
* console.log(p.contents); // 42
|
|
547
|
+
* p.contents = 100;
|
|
548
|
+
* console.log(x.value); // 100
|
|
549
|
+
* ```
|
|
550
|
+
*/
|
|
551
|
+
export function pointer(obj, POINTER_fn, sizeof, alloc, readValue, writeValue, c_void_p, native) {
|
|
552
|
+
let targetBuffer;
|
|
553
|
+
let baseType;
|
|
554
|
+
|
|
555
|
+
if (Buffer.isBuffer(obj)) {
|
|
556
|
+
targetBuffer = obj;
|
|
557
|
+
baseType = c_void_p; // Generic pointer
|
|
558
|
+
} else if (obj && obj._buffer) {
|
|
559
|
+
// Structure/Union instance or SimpleCData with _buffer
|
|
560
|
+
targetBuffer = obj._buffer;
|
|
561
|
+
// Get the base type - use constructor for SimpleCData, _structDef for structures
|
|
562
|
+
if (obj.constructor && obj.constructor._type) {
|
|
563
|
+
// SimpleCData instance - use the class itself
|
|
564
|
+
baseType = obj.constructor;
|
|
565
|
+
} else {
|
|
566
|
+
// Structure/Union instance
|
|
567
|
+
baseType = obj._structDef || obj.__structDef || c_void_p;
|
|
568
|
+
}
|
|
569
|
+
} else {
|
|
570
|
+
throw new TypeError("pointer() argument must be a ctypes instance or Buffer");
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const PtrType = POINTER_fn(baseType, sizeof, alloc, readValue, writeValue, c_void_p, native);
|
|
574
|
+
return PtrType.fromBuffer(targetBuffer);
|
|
357
575
|
}
|