ClojureDart
ClojureDart copied to clipboard
How do you use Dart type annotations to allow a method to be called on an object that must be a specific type?
I am trying to use dart:ffi, and the examples use type annotations heavily. I tried to call a C function using dart:ffi from Clojure without type annotations, but it seems that some steps need them. Here is the code I used, after requiring "dart:ffi" with ":as ffi":
(defn main []
(let [lib (ffi.DynamicLibrary/open "/usr/lib/libc.so.6")
printf (-> lib (.lookup "printf") .asFunction)]
(printf "This is an FFI call.")))
This is based on the dart:ffi example named hello_world at https://dart.dev/guides/libraries/c-interop, except I tried to call printf using the Linux C standard library instead of writing my own C library. Compiling this code succeeds, but I get an error when I try to run the executable generated by "dart compile exe". It seems like I need to convert the Pointer<NativeType> object returned by the lookup method to a Pointer<NativeFunction> type. Here is the stack trace:
Unhandled exception:
NoSuchMethodError: Class 'Pointer<NativeType>' has no instance method 'asFunction'.
Receiver: Pointer<NativeType>: address=0x7fbba4f37850
Tried calling: asFunction()
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:38)
#1 _objectNoSuchMethod (dart:core-patch/object_patch.dart:85)
#2 main (file:///home/elijah/circuit-simulator/lib/cljd-out/circuit-simulator/dart.dart:11)
#3 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297)
#4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192)
I tried adding a type hint on the name of the let binding like this:
(defn main []
(let [lib (ffi.DynamicLibrary/open "/usr/lib/libc.so.6")
^#/(ffi/Pointer ffi/NativeFunction) printf-object (.lookup lib "printf")
printf (-> printf-object .asFunction)]
(printf "This is an FFI call.")))
But I got an error saying that Pointer<NativeType> is not a subtype of Pointer<NativeFunction> after running the executable generated by "dart compile exe":
Unhandled exception:
type 'Pointer<NativeType>' is not a subtype of type 'Pointer<NativeFunction<Function>>' in type cast
#0 main (file:///home/elijah/circuit-simulator/lib/cljd-out/circuit-simulator/dart.dart:11)
#1 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297)
#2 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192)
Putting the type cast before the expression has the same result, putting it before the method name itself does nothing, and passing the type as the first argument to .lookup after lib gives a compilation error. I checked the generated Dart code, and the let binding for printf-object generates the following code:
final d_ffi.Pointer<d_ffi.NativeFunction> printf_object$1=((lib$1.lookup("printf", )) as d_ffi.Pointer<d_ffi.NativeFunction>);
I am trying to make this line be something like what follows, although replacing the line with this code still says the class has no asFunction method, probably because I need to specify types for the arguments and return value of the function like the example does. How do I generate something like this from Clojure?
final d_ffi.Pointer<d_ffi.NativeFunction> printf_object$1=(lib$1.lookup<d_ffi.NativeFunction>("printf", ));