inko-lang / inko

A language for building concurrent software with confidence

Home Page:http://inko-lang.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow passing pointers to Inko methods to C functions

yorickpeterse opened this issue · comments

Description

Certain C libraries rely on the use of callback functions, such as GUIs or cURL. We should support passing references to module methods for such cases, allowing the use of these libraries from Inko.

To enable this, we extend the fn extern syntax to allow for bodies like so:

fn extern example_method(value: Int) -> Int {
  value
}

Here fn extern means that the function (explicitly) uses the C calling convention/ABI, not the Inko ABI. Name mangling is still applied nor will we offer a way to opt out, as Inko isn't meant to be used for writing a .so or .a library linked into other projects. Just as extern methods without a body, these methods can't be generic.

To pass a reference to the method, one uses mut example_method (note the lack of arguments), just as how pointers to C values are created using mut expr.

Blocked by

Related work

No response

Using this GTK tutorial as an example, we'd end up with something like this:

fn extern gtk_application_window_new(...) -> Pointer[UInt8]
fn extern gtk_window_set_title(...)
fn extern gtk_window_set_default_size(...)
fn extern gtk_window_present(...)

fn extern gtk_application_new(...) -> Pointer[UInt8]
fn extern g_signal_connect(...)
fn extern g_application_run(...) -> Int32
fn extern g_object_unref(...)

fn extern activate(app: Pointer[UInt8], data: Pointer[UInt8]) {
  let window = gtk_application_window_new(app)

  gtk_window_set_title(window, 'Window')
  gtk_window_set_default_size(window, 200, 200)
  gtk_window_present(window)
}

class async Main {
  fn async main {
    let app = gtk_application_new('org.gtk.example', G_APPLICATION_DEFAULT_FLAGS)

    g_signal_connect(app, 'activate', mut activate, 0x0 as Pointer[UInt8])

    let status = g_application_run(app, 0, 0x0 as Pointer[UInt8])

    g_object_unref(app)
  }
}