Skip to content

Commit

Permalink
Refactor.
Browse files Browse the repository at this point in the history
  • Loading branch information
dboris committed May 18, 2024
1 parent 556a51c commit 1bee417
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 86 deletions.
52 changes: 39 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

Camlkit provides OCaml bindings to the following Cocoa frameworks:
* [Foundation](https://developer.apple.com/documentation/foundation?language=objc)
(on all platforms)
(all platforms)
* [AppKit](https://developer.apple.com/documentation/appkit?language=objc)
(on macOS and [GNUStep](https://gnustep.github.io/))
(macOS and [GNUStep](https://gnustep.github.io/))
* [UIKit](https://developer.apple.com/documentation/uikit?language=objc)
(on iOS, macOS on Arm, and [Mac Catalyst](https://developer.apple.com/mac-catalyst/))
(iOS, macOS on Arm, and [Mac Catalyst](https://developer.apple.com/mac-catalyst/))
* [WebKit](https://developer.apple.com/documentation/webkit?language=objc)
(on iOS and macOS)
(iOS and macOS)
* [Vision](https://developer.apple.com/documentation/vision?language=objc)
(on iOS and macOS)
(iOS and macOS)
* [CoreImage](https://developer.apple.com/documentation/coreimage?language=objc)
(on iOS and macOS)
(iOS and macOS)
* [Photos](https://developer.apple.com/documentation/photos?language=objc)
(iOS and macOS)

## Features

Expand All @@ -29,13 +31,14 @@ Camlkit provides OCaml bindings to the following Cocoa frameworks:
## Sample programs

A few sample programs are provided in the
[example](https://github.com/dboris/camlkit-examples/) repository. To give you
[examples](https://github.com/dboris/camlkit-examples/) repository. To give you
a taste of what a program in Camlkit looks like, here is a "Hello World" iOS
application:

```ocaml
open Foundation
open Uikit
open Uikit_
open Runtime
module AppDelegate = struct
Expand All @@ -55,7 +58,7 @@ module AppDelegate = struct
label |> UILabel.setText (new_string "Hello from OCaml!");
label |> UILabel.setTextColor (UIColor._class_ |> UIColor.C.systemBlackColor);
label |> UILabel.setTextAlignment Uikit_._UITextAlignmentCenter;
label |> UILabel.setTextAlignment _UITextAlignmentCenter;
label |> UIView.setFrame screen_bounds;
view |> UIView.addSubview label;
Expand All @@ -82,7 +85,7 @@ let main () =
|> Objc.(CArray.of_list string)
|> Objc.CArray.start
in
Uikit_._UIApplicationMain argc argv nil (new_string "AppDelegate") |> exit
_UIApplicationMain argc argv nil (new_string "AppDelegate") |> exit
;;
let () = main ()
Expand All @@ -108,10 +111,12 @@ constructs by comparing the equivalent Objective-C and OCaml code.
[NSString stringWithUTF8String: "Hello"];
```
OCaml:
OCaml (showing multiple equivalent constructs):
```ocaml
NSObject.C.new_ NSObject._class_
_new_ NSObject._class_
NSString._class_ |> NSObject.C.alloc |> NSString.initWithUTF8String "Hello"
alloc NSString._class_ |> NSString.initWithUTF8String "Hello"
NSString._class_ |> NSString.C.stringWithUTF8String "Hello"
new_string "Hello"
```
Expand Down Expand Up @@ -165,6 +170,29 @@ constructs by comparing the equivalent Objective-C and OCaml code.
function, which makes sure the object will be sent the `release` message when
the OCaml reference to it is garbage collected.

* Using objects from frameworks when bindings are not available

The Objective-C runtime provides functions which enable you to get a hold
of an arbitrary class by name and send it an arbitrary message, eg:

```OCaml
let a_class = Objc.get_class "AClassThatINeed" in
let an_instance = alloc a_class |> init in
an_instance |> msg_send (selector "anArbitrarySelector") ~args: Objc_t.[] ~return: Objc_t.void
```

## Documentation

At this time, the documentation of the project is lacking. The framework
bindings follow a regular naming pattern, so if you know the Objective-C method
you want to call, figuring the name of the OCaml function should be easy.

Some usefull sources you may wish to examine include:
* [Objective-C runtime bindings and basic functionality](https://github.com/dboris/camlkit/blob/main/runtime/runtime.ml)
* [Representation of Objective-C types in OCaml](https://github.com/dboris/camlkit/blob/main/runtime/objc_t.ml)
* [Usage examples](https://github.com/dboris/camlkit-examples/)
* [The Ctypes documentation](https://ocaml.org/p/ctypes/latest/doc/Ctypes/index.html)

## Project status

The project is in active development but is still experimental. It can be
Expand All @@ -174,6 +202,4 @@ that the API is subject to change.
## Related projects

For iOS and Mac Catalyst development you will need to set up a cross-toolchain
from [opam-cross-ios](https://github.com/ocaml-cross/opam-cross-ios). A [macOS
cross-toolchain for Linux](https://github.com/dboris/opam-cross-macos) is also
available.
from [opam-cross-ios](https://github.com/ocaml-cross/opam-cross-ios).
2 changes: 2 additions & 0 deletions demo/dune
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
(enabled_if (or
(= %{context_name} device.ios)
(= %{context_name} simulator.ios)
(= %{context_name} simulator-arm.ios)
(= %{context_name} catalyst.ios)))
(libraries camlkit-base.foundation camlkit-gui.uikit))

Expand All @@ -14,6 +15,7 @@
(enabled_if (or
(= %{context_name} device.ios)
(= %{context_name} simulator.ios)
(= %{context_name} simulator-arm.ios)
(= %{context_name} catalyst.ios)))
(action (progn
(copy ../Info.plist Info.plist)
Expand Down
7 changes: 4 additions & 3 deletions demo/main.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
open Runtime
open Foundation
open Uikit
open Uikit_
open Runtime

module AppDelegate = struct
let show_hello _self _cmd _app _opts =
Expand All @@ -21,7 +22,7 @@ module AppDelegate = struct
label |> UILabel.setText (new_string "Hello from OCaml!");
label |> UILabel.setTextColor
(UIColor._class_ |> UIColor.C.systemBlackColor);
label |> UILabel.setTextAlignment Uikit_._UITextAlignmentCenter;
label |> UILabel.setTextAlignment _UITextAlignmentCenter;
label |> UIView.setFrame screen_bounds;
view |> UIView.addSubview label;

Expand All @@ -48,7 +49,7 @@ let main () =
|> Objc.(CArray.of_list string)
|> Objc.CArray.start
in
Uikit_._UIApplicationMain argc argv nil (new_string "AppDelegate") |> exit
_UIApplicationMain argc argv nil (new_string "AppDelegate") |> exit
;;

let () = main ()
32 changes: 11 additions & 21 deletions runtime/function_description.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ module Functions (F : Ctypes.FOREIGN) = struct
open F *)

module Functions = struct
module Objc =
struct

module Objc = struct
(** Returns the class definition of a specified class. *)
let get_class =
foreign "objc_getClass" (string @-> returning _Class)
Expand Down Expand Up @@ -51,9 +49,7 @@ module Functions = struct

end

module Class =
struct

module Class = struct
(** Returns the name of a class. *)
let get_name =
foreign "class_getName" (_Class @-> returning string)
Expand Down Expand Up @@ -88,17 +84,13 @@ module Functions = struct

end

module Object =
struct

module Object = struct
(** Returns the class of an object. *)
let get_class =
foreign "object_getClass" (id @-> returning _Class)
end

module Sel =
struct

module Sel = struct
let register_name =
foreign "sel_registerName" (string @-> returning _SEL)

Expand All @@ -111,20 +103,21 @@ module Functions = struct
foreign "sel_isEqual" (_SEL @-> _SEL @-> returning bool)
end

module Ivar =
struct

module Ivar = struct
(** Returns the offset of an instance variable. *)
let get_offset =
foreign "ivar_getOffset" (_Ivar @-> returning ptrdiff_t)

(** Returns the name of an instance variable. *)
let get_name =
foreign "ivar_getName" (_Ivar @-> returning string)

(** Returns the type string of an instance variable. *)
let get_type_encoding =
foreign "ivar_getTypeEncoding" (_Ivar @-> returning _Enc)
end

module Method =
struct
module Method = struct
(** Returns the name of a method. *)
let get_name =
foreign "method_getName" (_Method @-> returning _SEL)
Expand All @@ -144,14 +137,11 @@ module Functions = struct
(** Returns a string describing a method's parameter and return types. *)
let get_type_encoding =
foreign "method_getTypeEncoding" (_Method @-> returning string)

end

module Protocol =
struct
module Protocol = struct
(** Returns the name of a protocol. *)
let get_name =
foreign "protocol_getName" (_Protocol @-> returning string)

end
end
Loading

0 comments on commit 1bee417

Please sign in to comment.