Skip to content

Instantly share code, notes, and snippets.

@electricbolt
Created May 31, 2022 22:32
Show Gist options
  • Select an option

  • Save electricbolt/e95bb22f735c8a83bdf9fffaa3845997 to your computer and use it in GitHub Desktop.

Select an option

Save electricbolt/e95bb22f735c8a83bdf9fffaa3845997 to your computer and use it in GitHub Desktop.
Example of Flutter FFI extensions for calling Objective-C methods.
// ignore_for_file: non_constant_identifier_names
import 'dart:convert';
import 'dart:ffi';
import "package:ffi/ffi.dart";
/// # Get Objective-C singleton.
/// Pointer<Void> instance = objc_msgSend_object(objc_getClass('UIDevice'), 'currentDevice');
///
/// # Read String.
/// Pointer<Void> value = objc_msgSend_object(instance, 'localizedModel');
/// String s = NSStringToDartString(value);
///
/// # Read int, bool or double.
/// int i = objc_msgSend_int(instance, 'userInterfaceIdiom');
/// bool b = objc_msgSend_int(instance, 'isMultitaskingSupported') != 0;
/// double d = objc_msgSend_double(instance, 'batteryLevel');
final DynamicLibrary _library = DynamicLibrary.process();
/// Objective-C prototype:
/// id objc_getClass(const char *name);
Pointer<Void> Function(Pointer<Utf8>) _objc_getClass = _library
.lookup<NativeFunction<Pointer<Void> Function(Pointer<Utf8>)>>(
'objc_getClass')
.asFunction();
Pointer<Void> objc_getClass(String name) {
return _objc_getClass(name.toNativeUtf8());
}
/// Objective-C prototype:
/// SEL sel_registerName(const char *str);
Pointer<Void> Function(Pointer<Utf8>) _sel_registerName = _library
.lookup<NativeFunction<Pointer<Void> Function(Pointer<Utf8>)>>(
'sel_registerName')
.asFunction();
Pointer<Void> sel_registerName(String method) {
return _sel_registerName(method.toNativeUtf8());
}
/// Objective-C prototype:
/// void objc_msgSend(void)
Pointer<Void> Function(Pointer<Void>, Pointer<Void>) _objc_msgSend_object =
_library
.lookup<
NativeFunction<
Pointer<Void> Function(
Pointer<Void>, Pointer<Void>)>>('objc_msgSend')
.asFunction();
Pointer<Void> objc_msgSend_object(Pointer<Void> instance, String method) {
Pointer<Void> sel = sel_registerName(method);
return _objc_msgSend_object(instance, sel);
}
/// Objective-C prototype:
/// void objc_msgSend(void)
int Function(Pointer<Void>, Pointer<Void>) _objc_msgSend_int = _library
.lookup<NativeFunction<Int64 Function(Pointer<Void>, Pointer<Void>)>>(
'objc_msgSend')
.asFunction();
int objc_msgSend_int(Pointer<Void> instance, String method) {
Pointer<Void> sel = sel_registerName(method);
return _objc_msgSend_int(instance, sel);
}
/// Objective-C prototype:
/// void objc_msgSend(void)
double Function(Pointer<Void>, Pointer<Void>) _objc_msgSend_double = _library
.lookup<NativeFunction<Double Function(Pointer<Void>, Pointer<Void>)>>(
'objc_msgSend')
.asFunction();
double objc_msgSend_double(Pointer<Void> instance, String method) {
Pointer<Void> sel = sel_registerName(method);
return _objc_msgSend_double(instance, sel);
}
/// Objective-C prototype:
/// CFIndex CFStringGetLength(CFStringRef theString);
int Function(Pointer<Void>) CFStringGetLength = _library
.lookup<NativeFunction<Int64 Function(Pointer<Void>)>>('CFStringGetLength')
.asFunction();
final int kCFStringEncodingUTF8 = 0x08000100;
/// Objective-C prototype:
/// Boolean CFStringGetCString(CFStringRef theString, char *buffer, CFIndex bufferSize, CFStringEncoding encoding);
bool Function(Pointer<Void>, Pointer<Uint8>, int, int) CFStringGetCString =
_library
.lookup<
NativeFunction<
Bool Function(Pointer<Void>, Pointer<Uint8>, Int64,
Int32)>>('CFStringGetCString')
.asFunction();
/// Converts a NSString to a Dart string. If an error occurs '' is returned.
String NSStringToDartString(Pointer<Void> str) {
int length = CFStringGetLength(str);
print('length is $length');
Pointer<Uint8> buf = calloc<Uint8>(length + 1);
bool ok = CFStringGetCString(
str, buf, length + 1, kCFStringEncodingUTF8);
if (ok == false) return '';
String result = Utf8Decoder().convert(buf.asTypedList(length));
calloc.free(buf);
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment