-
-
Notifications
You must be signed in to change notification settings - Fork 416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support pony bare functions to be reachable externally. #4569
Comments
I believe --extfun is supposed to do what "-export-dynamic" does. Did you try --extfun while assigning the callback to a variable? |
Ah, okay - I need to remove my patch, recompile ponyc, and test that way. One moment caller... |
Or use a prebuilt ponyc with the |
It does not work with --extfun |
Proof:
The only difference between the two command lines is the additional -Wl,--export-dynamic. |
(For the record, I did it using just ponyc and --extfun and letting it complete the execution build without the --pass=obj) |
Let me build a minimal example to add to this PR. |
use "lib:gtk-4"
use "lib:glib-2.0"
use "lib:gobject-2.0"
use "actor_pinning"
use @gtk_init[None]()
use @gtk_builder_new_from_string[Pointer[GObject] tag](str: Pointer[U8] tag, length: I64)
use @gtk_builder_get_object[Pointer[GObject] tag](gobj: Pointer[GObject] tag, str: Pointer[U8] tag)
use @gtk_widget_set_visible[None](widget: Pointer[GObject] tag, visible: I32)
use @gtk_window_set_interactive_debugging[None](enable: I32)
use @g_main_context_default[Pointer[GMainContext]]()
use @g_main_context_iteration[I32](context: Pointer[GMainContext], mayblock: I32)
use @g_object_ref_sink[Pointer[GObject] tag](gobj: Pointer[GObject] tag)
use @g_object_ref[None](gobj: Pointer[GObject] tag)
use @printf[U32](fmt: Pointer[U8] tag, ...)
actor Main
new create(env': Env) =>
let q: GtkController = GtkController(env')
q.initialize_gtk()
actor GtkController
let env: Env
let auth: PinUnpinActorAuth
var builder: Pointer[GObject] tag = Pointer[GObject]
var window: Pointer[GObject] tag = Pointer[GObject]
var button: Pointer[GObject] tag = Pointer[GObject]
var me: GtkController tag
var active: Bool = true
// Must be present to stop the function being dead-coded
let cb: @{(): None} = Callbacks~button_clicked()
new create(env': Env) =>
env = env'
auth = PinUnpinActorAuth(env.root)
ActorPinning.request_pin(auth)
me = recover tag this end
be initialize_gtk() =>
if ActorPinning.is_successfully_pinned(auth) then
@printf("We are pinned\n".cstring())
@gtk_init()
summon_builder()
else
@printf("We are not pinned\n".cstring())
initialize_gtk()
end
be summon_builder() =>
@printf("summon_builder() called\n".cstring())
builder = @gtk_builder_new_from_string(UIXML().cstring(), UIXML().size().i64())
@g_object_ref(builder)
window = @gtk_builder_get_object(builder, "window".cstring())
@g_object_ref(window)
button = @gtk_builder_get_object(builder, "button".cstring())
@g_object_ref(button)
@gtk_window_set_interactive_debugging(1)
@gtk_widget_set_visible(window, 1)
loop()
fun loop() =>
let context: Pointer[GMainContext] = @g_main_context_default()
if (active) then
@g_main_context_iteration(context, 0)
loop()
else
@printf("Not In loop\n".cstring())
end
fun _final() =>
@printf("Pony has exited for some reason\n".cstring())
primitive UIXML
fun apply(): String val =>
"""
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.94.0 -->
<interface>
<!-- interface-name x.ui -->
<requires lib="gtk" version="4.12"/>
<object class="GtkWindow" id="window">
<child>
<object class="GtkButton" id="button">
<property name="label">Click Me!</property>
<signal name="clicked" handler="Callbacks_button_clicked_o"/>
</object>
</child>
</object>
</interface>
"""
primitive Callbacks
fun @button_clicked() =>
@printf("I have been clicked\n".cstring())
primitive GObject
primitive GMainContext |
(Note - this isn't representative of the final API - this is just raw FFI so we can get the example as short as possible for your testing). |
@redvers Given that your example requires external dependencies, can you provide a Dockerfile that someone could use to build an image that would allow for testing of your example program. |
I can try, it is not my area of expertise. |
We discussed in today's sync call. Both the Callbacks type and the bare function inside Callbacks are being eliminated by the reachability pass ( I suggested in the sync call that the best path forward here is an RFC for a new annotation that marks a function as "reachable" regardless of whether it's reachable from Pony code. And that annotation would not work for generic types, because we don't know which of the possible reifications of the generic type to mark as reachable. |
As per zulip discussion: https://ponylang.zulipchat.com/#narrow/channel/189985-beginner-help/topic/Hooking.20up.20pony.20bare.20functions.20via.20XML
The additional compile flags that I added to src/libponyc/codegen/genexe.c were:
I tested with --extfun, and ponyc (or I guess llvm), still removed the function.
In order for the function to not be removed by dead code removal, I assigned it to a variable like so:
Thanks,
Red
The text was updated successfully, but these errors were encountered: