node-ctypes 1.3.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.
Binary file
Binary file
@@ -74,6 +74,15 @@ export function createLibraryClasses(Library, LRUCache, _toNativeType, _toNative
74
74
  if (prop === "argtypes") return argtypes;
75
75
  if (prop === "restype") return restype;
76
76
  if (prop === "errcheck") return cachedFunc ? cachedFunc.errcheck : undefined;
77
+ if (prop === "callAsync") {
78
+ if (restype === undefined) {
79
+ throw new Error(`Function ${name}: restype not set`);
80
+ }
81
+ if (!cachedFunc) {
82
+ cachedFunc = cdll.func(name, restype, argtypes);
83
+ }
84
+ return cachedFunc.callAsync;
85
+ }
77
86
  return target[prop];
78
87
  },
79
88
  set(target, prop, value) {
@@ -172,39 +181,19 @@ export function createLibraryClasses(Library, LRUCache, _toNativeType, _toNative
172
181
  let callMethod;
173
182
 
174
183
  if (argCount === 0) {
175
- // FAST PATH: No arguments - direct call
176
- callMethod = function () {
177
- return ffiFunc.call();
184
+ // FAST PATH: No declared arguments - but still support variadic
185
+ callMethod = function (...args) {
186
+ if (args.length === 0) {
187
+ return ffiFunc.call();
188
+ }
189
+ // Variadic: pass all args directly
190
+ return ffiFunc.call(...args);
178
191
  };
179
192
  } else if (allPrimitive) {
180
- // FAST PATH: All primitive args - direct call without processing
181
- switch (argCount) {
182
- case 1:
183
- callMethod = function (a0) {
184
- return ffiFunc.call(a0);
185
- };
186
- break;
187
- case 2:
188
- callMethod = function (a0, a1) {
189
- return ffiFunc.call(a0, a1);
190
- };
191
- break;
192
- case 3:
193
- callMethod = function (a0, a1, a2) {
194
- return ffiFunc.call(a0, a1, a2);
195
- };
196
- break;
197
- case 4:
198
- callMethod = function (a0, a1, a2, a3) {
199
- return ffiFunc.call(a0, a1, a2, a3);
200
- };
201
- break;
202
- default:
203
- // Fallback for many args
204
- callMethod = function (...args) {
205
- return ffiFunc.call(...args);
206
- };
207
- }
193
+ // FAST PATH: All primitive args - use rest args to support variadic
194
+ callMethod = function (...args) {
195
+ return ffiFunc.call(...args);
196
+ };
208
197
  } else {
209
198
  // SLOW PATH: Has buffer/struct args - need to extract _buffer
210
199
  callMethod = function (...args) {
@@ -237,11 +226,54 @@ export function createLibraryClasses(Library, LRUCache, _toNativeType, _toNative
237
226
  };
238
227
  }
239
228
 
229
+ // =========================================================================
230
+ // ASYNC WRAPPER: same argument processing, but calls callAsync
231
+ // Returns a Promise instead of the result directly
232
+ // =========================================================================
233
+
234
+ let asyncCallMethod;
235
+
236
+ if (argCount === 0) {
237
+ asyncCallMethod = function (...args) {
238
+ if (args.length === 0) {
239
+ return ffiFunc.callAsync();
240
+ }
241
+ // Variadic: pass all args directly
242
+ return ffiFunc.callAsync(...args);
243
+ };
244
+ } else if (allPrimitive) {
245
+ asyncCallMethod = function (...args) {
246
+ return ffiFunc.callAsync(...args);
247
+ };
248
+ } else {
249
+ asyncCallMethod = function (...args) {
250
+ const processedArgs = [];
251
+
252
+ for (let i = 0; i < args.length; i++) {
253
+ const arg = args[i];
254
+ if (arg && typeof arg === "object") {
255
+ if (arg._buffer !== undefined && Buffer.isBuffer(arg._buffer)) {
256
+ processedArgs.push(arg._buffer);
257
+ } else if (Buffer.isBuffer(arg)) {
258
+ processedArgs.push(arg);
259
+ } else {
260
+ processedArgs.push(arg);
261
+ }
262
+ } else {
263
+ processedArgs.push(arg);
264
+ }
265
+ }
266
+
267
+ return ffiFunc.callAsync(...processedArgs);
268
+ };
269
+ }
270
+
240
271
  // Aggiungi metadata come proprietà non-enumerable per non interferire
241
272
  Object.defineProperties(callMethod, {
242
273
  funcName: { value: name },
243
274
  address: { value: ffiFunc.address },
244
275
  _ffi: { value: ffiFunc },
276
+ callAsync: { value: asyncCallMethod, writable: false, enumerable: false, configurable: false },
245
277
  // Esponi errcheck come setter/getter
246
278
  errcheck: {
247
279
  get() {
package/lib/index.d.ts CHANGED
@@ -79,6 +79,8 @@ export type ErrcheckCallback = (result: any, func: CallableFunction, args: any[]
79
79
  /** FFI function wrapper */
80
80
  export interface FFIFunction {
81
81
  (...args: any[]): any;
82
+ /** Async version: executes the native call on a worker thread, returns a Promise */
83
+ callAsync(...args: any[]): Promise<any>;
82
84
  readonly funcName: string;
83
85
  readonly address: bigint;
84
86
  errcheck: ErrcheckCallback | null;
@@ -87,7 +89,7 @@ export interface FFIFunction {
87
89
  /** CDLL - C calling convention library */
88
90
  export class CDLL {
89
91
  constructor(path: string | null);
90
- func(name: string, returnType: AnyType, argTypes?: AnyType[], options?: FunctionOptions): CallableFunction & { errcheck: ErrcheckCallback | null };
92
+ func(name: string, returnType: AnyType, argTypes?: AnyType[], options?: FunctionOptions): CallableFunction & { callAsync(...args: any[]): Promise<any>; errcheck: ErrcheckCallback | null };
91
93
  symbol(name: string): bigint;
92
94
  close(): void;
93
95
  readonly path: string;
@@ -99,6 +101,8 @@ export class CDLL {
99
101
  /** FunctionWrapper for Python-like argtypes/restype syntax */
100
102
  export interface FunctionWrapper {
101
103
  (...args: any[]): any;
104
+ /** Async version: executes the native call on a worker thread, returns a Promise */
105
+ callAsync(...args: any[]): Promise<any>;
102
106
  argtypes: AnyType[];
103
107
  restype: AnyType;
104
108
  errcheck: ErrcheckCallback | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-ctypes",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Python ctypes-like FFI for Node.js using libffi",
5
5
  "author": "Damiano Mazzella",
6
6
  "license": "MIT",