Loading...
Loading...
Bridge Dart with native C/C++ libraries using FFI.
npx skill4agent add dart-lang/skills dart-native-interop-ffidart:ffi.so.dylib.dllpackage:ffigentypedefcallocmallocpackage:ffiFinalizableNativeFinalizerintlongsize_tabiSpecificIntegerIntLongSizeInt32Int64.hffigenpackage:ffigenffigen.yamlname: NativeLibrary
description: Bindings for native C library.
output: 'lib/src/generated_bindings.dart'
headers:
entry-points:
- 'src/native_lib.h'
include-directives:
- '**native_lib.h'
ffi-native:
asset: 'native_lib'dart run ffigen --config ffigen.yamlimport 'dart:ffi' as ffi;
import 'dart:io' show Platform;
import 'package:path/path.dart' as path;
ffi.DynamicLibrary loadNativeLibrary(String libraryName) {
if (Platform.isMacOS || Platform.isIOS) {
return ffi.DynamicLibrary.open('lib$libraryName.dylib');
} else if (Platform.isWindows) {
return ffi.DynamicLibrary.open('$libraryName.dll');
} else {
return ffi.DynamicLibrary.open('lib$libraryName.so');
}
}
final dylib = loadNativeLibrary('hello');ffigenAbiSpecificIntegerimport 'dart:ffi' as ffi;
// C signature: void hello_world();
typedef hello_world_func = ffi.Void Function();
// Dart signature
typedef HelloWorld = void Function();
// C signature: long process_data(size_t size);
// PREFER AbiSpecificInteger (Long, Size) over Int64/Int32
typedef process_data_func = ffi.Long Function(ffi.Size size);
typedef ProcessData = int Function(int size);
final HelloWorld hello = dylib
.lookup<ffi.NativeFunction<hello_world_func>>('hello_world')
.asFunction();callocFinalizableNativeFinalizerimport 'dart:ffi' as ffi;
import 'package:ffi/ffi.dart'; // Provides calloc, malloc, Utf8
// 1. Manual Allocation
ffi.Pointer<Utf8> allocateString(String dartString) {
// DO manually allocate memory using calloc
final ffi.Pointer<Utf8> cString = dartString.toNativeUtf8(allocator: calloc);
return cString;
}
void freeMemory(ffi.Pointer pointer) {
// DO manually free memory
calloc.free(pointer);
}
// 2. Native Finalizer for C-allocated memory
// Assume C provides: void free_resource(Resource* res);
final ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer)>> freeResourcePtr =
dylib.lookup('free_resource');
final ffi.NativeFinalizer _finalizer = ffi.NativeFinalizer(freeResourcePtr.cast());
class NativeResourceWrapper implements ffi.Finalizable {
final ffi.Pointer<ffi.Void> _cResource;
NativeResourceWrapper(this._cResource) {
// DO use Finalizable and NativeFinalizer to ensure cleanup
_finalizer.attach(this, _cResource.cast(), detach: this);
}
void dispose() {
_finalizer.detach(this);
// Manually call the free function if disposed early
final freeFunc = freeResourcePtr.asFunction<void Function(ffi.Pointer)>();
freeFunc(_cResource);
}
}Invalid argument(s): Unknown libraryInt32Int64longintsize_tabiSpecificIntegerffi.Longffi.Intffi.Sizecallocmallocfreepackage:ffigendart-concurrency-isolatesdart:ioPlatformpackage:path