Skip to content

Commit

Permalink
Refactor.
Browse files Browse the repository at this point in the history
  • Loading branch information
dboris committed Oct 3, 2024
1 parent d284018 commit 835f3bc
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 56 deletions.
72 changes: 32 additions & 40 deletions camlkit/camlkit.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
open Foundation
open Runtime
open Define
open Objc

module Appkit_global = Appkit_global

Expand All @@ -24,38 +24,37 @@ module Appkit_AppDelegate = struct
end

module Create (D : S) = struct
open Define
(** Note:
[get_protocol "NSApplicationDelegate"] fails since its object is not created
by the runtime unless referenced in ObjC code:
https://stackoverflow.com/questions/10212119/objc-getprotocol-returns-null-for-nsapplicationdelegate
But it's an informal protocol, not required for the code to function.
*)

let _class_ = Class.define D.class_name
let self = Class.define D.class_name
~methods:
[ _method_
[ Method.define
~cmd: (selector "applicationWillFinishLaunching:")
~args: Objc_t.[id]
~return: Objc_t.void
(fun _self _cmd notification ->
D.on_before_start notification)

; _method_
; Method.define
~cmd: (selector "applicationDidFinishLaunching:")
~args: Objc_t.[id]
~return: Objc_t.void
(fun _self _cmd notification ->
D.on_started notification)

; _method_
; Method.define
~cmd: (selector "applicationWillTerminate:")
~args: Objc_t.[id]
~return: Objc_t.void
(fun _self _cmd notification ->
D.on_before_terminate notification)

; _method_
; Method.define
~cmd: (selector "applicationShouldTerminateAfterLastWindowClosed:")
~args: Objc_t.[id]
~return: Objc_t.bool
Expand All @@ -68,44 +67,42 @@ end
module CamlProxy = struct
module type S = sig
val class_name : string
val ivars : ivar_spec' list
val ivars : Define.ivar_spec' list
val init : object_t -> object_t
val method_signature_for_selector : string -> Objc_t._Enc
val handle_invocation : object_t -> object_t -> unit
end

module Create (D : S) = struct
let methods =
[ _method_ (fun self _cmd -> D.init self)
[ Method.define (fun self _cmd -> D.init self)
~cmd: (selector "init")
~args: Objc_t.[]
~return: Objc_t.id

; _method_
; Method.define
(fun self _cmd invocation -> D.handle_invocation invocation self)
~cmd: (selector "forwardInvocation:")
~args: Objc_t.[id]
~return: Objc_t.void

; _method_
; Method.define
~cmd: (selector "methodSignatureForSelector:")
~args: Objc_t.[_SEL]
~return: Objc_t.id
(fun _self _cmd sel ->
Objc.(msg_send
~self: (get_class "NSMethodSignature")
~cmd: (selector "signatureWithObjCTypes:")
~typ: (_Enc @-> returning id)
(D.method_signature_for_selector (string_of_selector sel))))
NSMethodSignature.self
|> NSMethodSignatureClass.signatureWithObjCTypes
(D.method_signature_for_selector (string_of_selector sel)))
]
let class_methods =
[ _method_ (fun self _cmd -> self |> alloc |> init)
[ Method.define (fun self _cmd -> self |> alloc |> init)
~cmd: (selector "new")
~args: Objc_t.[]
~return: Objc_t.id
]

let _class_ =
let self =
Class.define D.class_name ~superclass: NSProxy.self
~methods ~class_methods ~ivars: D.ivars
end
Expand All @@ -123,18 +120,18 @@ module CamlObjectProxy = struct

(** Initialize the proxy object with the target object *)
let init_with_target_object target_object self =
Objc.(msg_send ~self
msg_send ~self
~cmd: (selector "initWithTargetObject:")
~typ: (id @-> returning id)
target_object)
target_object
;;

let _class_ =
let self =
let ivar_name = "targetObject" in

let responds_to_selector_imp self cmd sel =
D.responds_to_selector (string_of_selector sel) ||
Objc.(msg_send
(msg_send
~self: (self |> get_property ~typ: id ivar_name |> Object.get_class)
~cmd
~typ: (_SEL @-> returning bool)
Expand All @@ -145,59 +142,54 @@ module CamlObjectProxy = struct
if D.responds_to_selector (string_of_selector sel) then
D.handle_invocation invocation self
else
Objc.msg_send_ov
~self: invocation
~cmd: (selector "invokeWithTarget:")
(self |> get_property ~typ: id ivar_name)

invocation
|> NSInvocation.invokeWithTarget
(self |> get_property ~typ: id ivar_name)
and method_signature_for_selector_imp self cmd sel =
let str_sel = string_of_selector sel in
if D.responds_to_selector str_sel then
Objc.(msg_send
~self: (get_class "NSMethodSignature")
~cmd: (selector "signatureWithObjCTypes:")
~typ: (_Enc @-> returning id)
(D.method_signature_for_selector str_sel))
NSMethodSignature.self
|> NSMethodSignatureClass.signatureWithObjCTypes
(D.method_signature_for_selector str_sel)
else
Objc.(msg_send
msg_send
~self: (self |> get_property ~typ: id ivar_name)
~cmd
~typ: (_SEL @-> returning id)
sel)
sel
in
let methods =
[ Property.obj_getter ~ivar_name ~typ: id ~enc: Objc_t.(Encode.value id)
; Property.obj_setter ~ivar_name ~typ: id ~enc: Objc_t.(Encode.value id) ()

; _method_
; Method.define
~cmd: (selector "initWithTargetObject:")
~args: Objc_t.[id]
~return: Objc_t.id
(fun self _cmd target ->
self |> set_property ~typ: id ivar_name target;
self)

; _method_
; Method.define
~cmd: (selector "forwardInvocation:")
~args: Objc_t.[id]
~return: Objc_t.void
forward_invocation_imp

; _method_
; Method.define
~cmd: (selector "methodSignatureForSelector:")
~args: Objc_t.[_SEL]
~return: Objc_t.id
method_signature_for_selector_imp
]
and class_methods =
[ _method_
[ Method.define
~cmd: (selector "respondsToSelector:")
~args: Objc_t.[_SEL]
~return: Objc_t.bool
responds_to_selector_imp
]
and ivars =
[ ivar_spec ~name: ivar_name ~typ: id ~enc: Objc_t.(Encode.value id) ]
and ivars = [ Ivar.define ivar_name Objc_t.id ]
in
Class.define D.class_name
~superclass: NSProxy.self ~ivars ~methods ~class_methods
Expand Down
29 changes: 17 additions & 12 deletions runtime/runtime.ml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
include C.Types
include Ctypes

open C.Types
open Ctypes
open Foreign
open Unsigned

module Platform = Platform
module Protocol = C.Functions.Protocol
Expand All @@ -26,15 +26,15 @@ module Class = struct

let alignment_of_size size =
let open Float in
Unsigned.Size_t.to_int size
Size_t.to_int size
|> of_int
|> log2
|> round
|> to_int
|> Unsigned.UInt8.of_int
|> UInt8.of_int
;;

let create_instance ?(extra_bytes = Unsigned.Size_t.of_int 0) cls =
let create_instance ?(extra_bytes = Size_t.of_int 0) cls =
create_instance cls extra_bytes

let add_method ~self ~cmd ~typ ~imp ~enc =
Expand Down Expand Up @@ -84,7 +84,7 @@ module Class = struct
assert (add_protocol self proto));

ivars |> List.iter (fun (IvarSpec {name; typ; enc}) ->
let size = Unsigned.Size_t.of_int (sizeof typ) in
let size = Size_t.of_int (sizeof typ) in
assert (add_ivar ~self ~name ~size ~enc));

Objc.register_class self;
Expand Down Expand Up @@ -153,6 +153,7 @@ let to_selector = coerce (ptr void) _SEL

module Objc = struct
include C.Functions.Objc
include C.Types
include Ctypes
include Unsigned
include Signed
Expand Down Expand Up @@ -239,6 +240,9 @@ let retain self = Objc.msg_send_vo ~self ~cmd: (selector "retain")
let release self =
Objc.msg_send ~self ~cmd: (selector "release") ~typ: (returning void)

let autorelease self =
Objc.msg_send ~self ~cmd: (selector "autorelease") ~typ: (returning void)

(** Release ObjC object when OCaml ptr is garbage collected. *)
let gc_autorelease self =
Gc.finalise release self;
Expand All @@ -254,7 +258,8 @@ let nsstring_class = Objc.get_class "NSString"

(** Creates a new NSString object autoreleased by OCaml's GC. *)
let new_string str =
Objc.msg_send ~self:nsstring_class
Objc.msg_send
~self: nsstring_class
~cmd: (selector "stringWithUTF8String:")
~typ: (string @-> returning id)
str
Expand Down Expand Up @@ -290,7 +295,7 @@ let is_nil = is_null

module Bitmask = struct
let of_list = List.fold_left Int.logor Int.zero
let of_list' = List.fold_left Unsigned.ULLong.logor Unsigned.ULLong.zero
let of_list' = List.fold_left ULLong.logor ULLong.zero
let (+) = Int.logor
end

Expand All @@ -302,8 +307,8 @@ module Block_descriptor = struct
let () = seal t
let make sz =
let d = make t in
setf d reserved (Unsigned.ULLong.of_int 0);
setf d size (Unsigned.ULLong.of_int sz);
setf d reserved (ULLong.of_int 0);
setf d size (ULLong.of_int sz);
d
end

Expand All @@ -327,7 +332,7 @@ module Block = struct
let b = make t in
setf b isa self;
setf b descriptor desc_ptr;
setf b invoke (coerce (Foreign.funptr typ) (ptr void) f);
setf b invoke (coerce (funptr typ) (ptr void) f);
setf b flags block_is_global;
allocate t b |> coerce (ptr t) (ptr void)

Expand Down
4 changes: 2 additions & 2 deletions test/test-camlkit/test_camlkit.ml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ let test_define_custom_class () =
;;
end)
in
let obj = MyCustomClass._class_ |> alloc |> init in
let obj = MyCustomClass.self |> alloc |> init in
let expected = 5 * 2
and actual =
Objc.msg_send ~self: obj
Expand Down Expand Up @@ -89,7 +89,7 @@ let test_define_CamlObjectProxy_class () =
in
let str = "Hello" in
let obj =
NSStringCamlProxy.(alloc _class_ |> init_with_target_object (new_string str))
NSStringCamlProxy.(alloc self |> init_with_target_object (new_string str))
in
let x = 5 in
let expected = x * 3
Expand Down
4 changes: 2 additions & 2 deletions test/test-dispatch/test_dispatch.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ let serial_queue = dispatch_queue_create "TestQueue2" _DISPATCH_QUEUE_SERIAL

let test_dispatch_queue_concurrent () =
let handler_called = ref false in
dispatch_sync_f concur_queue null (fun _ctx -> handler_called := true);
dispatch_sync_f concur_queue nil (fun _ctx -> handler_called := true);
A.check A.bool "dispatched function was called" true !handler_called
;;

Expand All @@ -24,7 +24,7 @@ let test_dispatch_queue_concurrent_with_block () =

let test_dispatch_queue_serial () =
let handler_called = ref false in
dispatch_sync_f serial_queue null (fun _ctx -> handler_called := true);
dispatch_sync_f serial_queue nil (fun _ctx -> handler_called := true);
A.check A.bool "dispatched function was called" true !handler_called
;;

Expand Down

0 comments on commit 835f3bc

Please sign in to comment.