* Difficulty integrating with Swift/Objective-C
@ 2021-09-05 6:03 paul
2021-09-05 8:26 ` Taylan Kammer
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: paul @ 2021-09-05 6:03 UTC (permalink / raw)
To: guile-user
Good day,
I have an existing app which is written in Swift and runs on macOS
10.15. I would like to provide users a way of customising the app
(initially just simple things like modifying keybindings for
example, later hopefully more) and as a keen Emacs user, i'm
inspired by the idea of providing a Schemey/Lispy interface for
such extensions. Guile looks like it'd be great for this. If i
understand correctly, it'd be best if i could bundle the Guile
runtime as a static library with the app, and call out to it to
evaluate user-provided code. I haven't thought deeply about this
interface yet; i thought i'd get a proof-of-concept working first.
I wonder if i might humbly ask for some guidance on how to get it
working, because after a couple of days i seem to have failed.
I'm no C/threads/low-level guru, so my apologies if i'm doing
something very dumb.
I had some difficulty getting my app to compile against Guile, but
i eventually managed to link against a version of Guile installed
with Homebrew (guile: stable 3.0.7 (bottled)), however when trying
to boot it up i seemed to run into the same issue described by
Jeffrey Walton [1]. My app would boot, and as soon as it hit the
Guile initialisation calls, it would error with "allocating JIT
code buffer failed: Permission denied, jit.c:5804: fatal:
assertion failed". While that person seems to imply the problem
is with Apple's M1 silicon, i'm actually running an older machine
(2.9 GHz Dual-Core Intel Core i5, macOS 11.5.2). I then managed
to get further by downloading the Guile release tarball version
3.0.7 and and building with `./configure --enable-jit=no`; this
got me a bit further, however it still didn't work: i think it is
because some assumption Guile has about the thread it runs on, or
when it's invoked, is violated.. but i'm unsure how to find out.
What i currently have, is this snippet. It's being called from
Swift land, in the `applicationDidFinishLaunching(_ aNotification:
Notification)` function. As far as i can tell, that _is_ the main
thread.
```
#include "libguile.h"
static void* register_functions (void* data)
{
SCM test = scm_c_eval_string("(+ 3 5)");
int foo = scm_to_int(test);
printf("foo = %d\n", foo);
return NULL;
}
void run_guile() {
printf("hello from C, before Guile\n");
scm_init_guile();
//scm_with_guile(®ister_functions, NULL); // i've tried
only having this line uncommented, too, but that also causes
immediate crashes
//scm_shell(0, NULL);
}
```
This compiles fine, and i see the "hello from C" line printed, but
then it crashes. The error seems to vary, here are some i've
seen:
1. "Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)" at line 182 of
pairs.h,
2. "Pre-boot error; key: misc-error, args: ("%search-path" "path
is not a proper list: ~a" (("/usr/local/share/guile/3.0"
"/usr/local/share/guile/site/3.0" "/usr/local/share/guile/site"
. #<program 12503b140 124fc10fc>)) #f)", "Thread 1: signal
SIGABRT", line 260 of throw.c
3. "Thread 1: EXC_BAD_ACCESS (code=1, address=0x9)", at line 585
of weak-set.c.
4. I've also sometimes seen this one,
https://lists.gnu.org/archive/html/emacs-bug-tracker/2020-01/msg00365.html,
although perhaps that's indeed related to closed stdout.
Because these errors are different all the time i guess it's some
race condition or threading issue? I wonder if someone knows an
avenue i can attempt to use to debug what's going on? 🙏
All the best,
paul
1. https://mail.gnu.org/archive/html/bug-guile/2021-03/msg00012.html
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Difficulty integrating with Swift/Objective-C
2021-09-05 6:03 Difficulty integrating with Swift/Objective-C paul
@ 2021-09-05 8:26 ` Taylan Kammer
2021-09-05 9:35 ` paul
2021-09-06 10:21 ` paul
2021-09-05 10:56 ` Chris Vine
2021-09-08 23:59 ` paul
2 siblings, 2 replies; 10+ messages in thread
From: Taylan Kammer @ 2021-09-05 8:26 UTC (permalink / raw)
To: paul, guile-user
On 05.09.2021 08:03, paul wrote:
> Good day,
>
> I have an existing app which is written in Swift and runs on macOS 10.15. I would like to provide users a way of customising the app (initially just simple things like modifying keybindings for example, later hopefully more) and as a keen Emacs user, i'm inspired by the idea of providing a Schemey/Lispy interface for such extensions. Guile looks like it'd be great for this. If i understand correctly, it'd be best if i could bundle the Guile runtime as a static library with the app, and call out to it to evaluate user-provided code. I haven't thought deeply about this interface yet; i thought i'd get a proof-of-concept working first. I wonder if i might humbly ask for some guidance on how to get it working, because after a couple of days i seem to have failed. I'm no C/threads/low
-level guru, so my apologies if i'm doing something very dumb.
>
> I had some difficulty getting my app to compile against Guile, but i eventually managed to link against a version of Guile installed with Homebrew (guile: stable 3.0.7 (bottled)), however when trying to boot it up i seemed to run into the same issue described by Jeffrey Walton [1]. My app would boot, and as soon as it hit the Guile initialisation calls, it would error with "allocating JIT code buffer failed: Permission denied, jit.c:5804: fatal: assertion failed". While that person seems to imply the problem is with Apple's M1 silicon, i'm actually running an older machine (2.9 GHz Dual-Core Intel Core i5, macOS 11.5.2). I then managed to get further by downloading the Guile release tarball version 3.0.7 and and building with `./configure --enable-jit=no`; this got me a bit further
, however it still didn't work: i think it is because some assumption Guile has about the thread it runs on, or when it's invoked, is violated.. but i'm unsure how to find out.
>
> What i currently have, is this snippet. It's being called from Swift land, in the `applicationDidFinishLaunching(_ aNotification: Notification)` function. As far as i can tell, that _is_ the main thread.
>
> ```
> #include "libguile.h"
>
> static void* register_functions (void* data)
> {
> SCM test = scm_c_eval_string("(+ 3 5)");
> int foo = scm_to_int(test);
> printf("foo = %d\n", foo);
>
> return NULL;
> }
>
> void run_guile() {
> printf("hello from C, before Guile\n");
> scm_init_guile();
> //scm_with_guile(®ister_functions, NULL); // i've tried only having this line uncommented, too, but that also causes immediate crashes
> //scm_shell(0, NULL);
> }
> ```
>
> This compiles fine, and i see the "hello from C" line printed, but then it crashes. The error seems to vary, here are some i've seen:
>
> 1. "Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)" at line 182 of pairs.h,
> 2. "Pre-boot error; key: misc-error, args: ("%search-path" "path is not a proper list: ~a" (("/usr/local/share/guile/3.0" "/usr/local/share/guile/site/3.0" "/usr/local/share/guile/site" . #<program 12503b140 124fc10fc>)) #f)", "Thread 1: signal SIGABRT", line 260 of throw.c
> 3. "Thread 1: EXC_BAD_ACCESS (code=1, address=0x9)", at line 585 of weak-set.c.
> 4. I've also sometimes seen this one, https://lists.gnu.org/archive/html/emacs-bug-tracker/2020-01/msg00365.html, although perhaps that's indeed related to closed stdout.
>
> Because these errors are different all the time i guess it's some race condition or threading issue? I wonder if someone knows an avenue i can attempt to use to debug what's going on? 🙏
>
> All the best,
> paul
>
> 1. https://mail.gnu.org/archive/html/bug-guile/2021-03/msg00012.html
>
Hi Paul,
To narrow down the issue, I'd attempt a few things, in order:
1. Compile only the C code, adding a main() function, just to make sure the OS
and the chosen Guile version and such are working fine with each other.
2. Compile pure Objective-C code, calling that run_guile() function firstly
directly from the main() function in main.m of the Objective-C program, and
commenting out the NSApplicationMain() call that would initialize Apple's
application framework.
3. See if reactivating the NSApplicationMain() call causes problems. (It should
be called *after* the Guile initialization.)
4. See if you can use Guile's C functions from -applicationDidFinishLaunching:
e.g. by doing: scm_c_eval_string("(begin (display 'HelloWorld) (newline))")
If that works, we now have an Objective-C + Guile application, and want to move
to using Swift instead. This is where my Apple knowledge hits its limits because
I never used Swift. :-)
But I guess Swift should have something equivalent to the main() function of C and
Objective-C, and calling Guile initialization from there might do the trick.
If you hit a problem in step 3 or 4, then it could mean that Guile and Cocoa are
somehow incompatible as they both want to apply some magic to the C program while
initializing themselves. I wouldn't know how to approach that issue.
--
Taylan
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Difficulty integrating with Swift/Objective-C
2021-09-05 8:26 ` Taylan Kammer
@ 2021-09-05 9:35 ` paul
2021-09-06 10:21 ` paul
1 sibling, 0 replies; 10+ messages in thread
From: paul @ 2021-09-05 9:35 UTC (permalink / raw)
To: Taylan Kammer, guile-user
Hey Taylan,
Thank you for your reply!
On 2021-09-05 at 18:26 AEST, quoth Taylan Kammer
<taylan.kammer@gmail.com>:
> To narrow down the issue, I'd attempt a few things, in order:
>
> 1. Compile only the C code, adding a main() function, just to
> make sure the OS
> and the chosen Guile version and such are working fine with
> each other.
>
> 2. Compile pure Objective-C code, calling that run_guile()
> function firstly
> directly from the main() function in main.m of the
> Objective-C program, and
> commenting out the NSApplicationMain() call that would
> initialize Apple's
> application framework.
>
> 3. See if reactivating the NSApplicationMain() call causes
> problems. (It should
> be called *after* the Guile initialization.)
>
> 4. See if you can use Guile's C functions from
> -applicationDidFinishLaunching:
> e.g. by doing: scm_c_eval_string("(begin (display
> 'HelloWorld) (newline))")
>
> If that works, we now have an Objective-C + Guile application,
> and want to move
> to using Swift instead. This is where my Apple knowledge hits
> its limits because
> I never used Swift. :-)
>
> But I guess Swift should have something equivalent to the main()
> function of C and
> Objective-C, and calling Guile initialization from there might
> do the trick.
>
> If you hit a problem in step 3 or 4, then it could mean that
> Guile and Cocoa are
> somehow incompatible as they both want to apply some magic to
> the C program while
> initializing themselves. I wouldn't know how to approach that
> issue.
Actually, in my case there is no Objective-C code, only Swift, but
these suggestions definitely give me some inspiration for things
to try. I'll see if i can figure out how the NSApplication is
bootstrapped so that i can hook in before that, because indeed,
the way i tried, i was attempting to initialise Guile from deep
within Application Kit code, which could be doomed to fail :).
Anyway i am heading away from my computer now, but will definitely
give this angle a try — thanks for taking the time to reply!
Kind regards,
p.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Difficulty integrating with Swift/Objective-C
2021-09-05 6:03 Difficulty integrating with Swift/Objective-C paul
2021-09-05 8:26 ` Taylan Kammer
@ 2021-09-05 10:56 ` Chris Vine
2021-09-06 10:26 ` paul
2021-09-08 23:59 ` paul
2 siblings, 1 reply; 10+ messages in thread
From: Chris Vine @ 2021-09-05 10:56 UTC (permalink / raw)
To: guile-user
On Sun, 05 Sep 2021 16:03:24 +1000
paul <paul@inktvis.org> wrote:
> Good day,
>
> I have an existing app which is written in Swift and runs on macOS
> 10.15. I would like to provide users a way of customising the app
> (initially just simple things like modifying keybindings for
> example, later hopefully more) and as a keen Emacs user, i'm
> inspired by the idea of providing a Schemey/Lispy interface for
> such extensions. Guile looks like it'd be great for this. If i
> understand correctly, it'd be best if i could bundle the Guile
> runtime as a static library with the app, and call out to it to
> evaluate user-provided code. I haven't thought deeply about this
> interface yet; i thought i'd get a proof-of-concept working first.
> I wonder if i might humbly ask for some guidance on how to get it
> working, because after a couple of days i seem to have failed.
> I'm no C/threads/low-level guru, so my apologies if i'm doing
> something very dumb.
>
> I had some difficulty getting my app to compile against Guile, but
> i eventually managed to link against a version of Guile installed
> with Homebrew (guile: stable 3.0.7 (bottled)), however when trying
> to boot it up i seemed to run into the same issue described by
> Jeffrey Walton [1]. My app would boot, and as soon as it hit the
> Guile initialisation calls, it would error with "allocating JIT
> code buffer failed: Permission denied, jit.c:5804: fatal:
> assertion failed". While that person seems to imply the problem
> is with Apple's M1 silicon, i'm actually running an older machine
> (2.9 GHz Dual-Core Intel Core i5, macOS 11.5.2). I then managed
> to get further by downloading the Guile release tarball version
> 3.0.7 and and building with `./configure --enable-jit=no`; this
> got me a bit further, however it still didn't work: i think it is
> because some assumption Guile has about the thread it runs on, or
> when it's invoked, is violated.. but i'm unsure how to find out.
>
> What i currently have, is this snippet. It's being called from
> Swift land, in the `applicationDidFinishLaunching(_ aNotification:
> Notification)` function. As far as i can tell, that _is_ the main
> thread.
>
> ```
> #include "libguile.h"
>
> static void* register_functions (void* data)
> {
> SCM test = scm_c_eval_string("(+ 3 5)");
> int foo = scm_to_int(test);
> printf("foo = %d\n", foo);
>
> return NULL;
> }
>
> void run_guile() {
> printf("hello from C, before Guile\n");
> scm_init_guile();
> //scm_with_guile(®ister_functions, NULL); // i've tried
> only having this line uncommented, too, but that also causes
> immediate crashes
> //scm_shell(0, NULL);
> }
> ```
>
> This compiles fine, and i see the "hello from C" line printed, but
> then it crashes. The error seems to vary, here are some i've
> seen:
>
> 1. "Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)" at line 182 of
> pairs.h,
> 2. "Pre-boot error; key: misc-error, args: ("%search-path" "path
> is not a proper list: ~a" (("/usr/local/share/guile/3.0"
> "/usr/local/share/guile/site/3.0" "/usr/local/share/guile/site"
> . #<program 12503b140 124fc10fc>)) #f)", "Thread 1: signal
> SIGABRT", line 260 of throw.c
> 3. "Thread 1: EXC_BAD_ACCESS (code=1, address=0x9)", at line 585
> of weak-set.c.
> 4. I've also sometimes seen this one,
> https://lists.gnu.org/archive/html/emacs-bug-tracker/2020-01/msg00365.html,
> although perhaps that's indeed related to closed stdout.
>
> Because these errors are different all the time i guess it's some
> race condition or threading issue? I wonder if someone knows an
> avenue i can attempt to use to debug what's going on? 🙏
You appear to want to run scheme code as an extension language, via the
guile VM, in a program written for MacOS in the Swift language. I know
nothing about the Swift language and whether it has a sufficient C-like
FFI to achieve this, but you may get some inspiration from the
following, which enables scheme code to be run as an extension language
within a C++ program:
https://sourceforge.net/p/cxx-gtk-utils/git/ci/master/tree/c++-gtk-utils/extension.h
However there are various issues. First, guile's exceptions
(based on C's longjmp()/setjmp() and cognates) are almost certainly
not implemented in the same way as Swift's exceptions (assuming Swift
has exceptions), which means amongst other things that, if Swift has
something akin to destructors/deinitialization, you should not allow
guile exceptions to leave Swift objects undestroyed were guile to
jump out of local scope on raising an exception (scm_dynwind_begin(),
scm_dynwind_end and scm_dynwind_unwind_handler can be useful here if
you are able to manage your Swift objects manually in C). Nor more
generally should you allow Swift exceptions (if Swift has them) to
escape out of a guile scm_dynwind_begin()/scm_dynwind_end() pair, or
you will stop guile's resource management working correctly.
Secondly, there are some issues relating to the fact that guile's
'make-fresh-user-module' and 'load' procedures leak memory, which can
be problematic if all tasks run as scheme code are not to share the
same top level.
Thirdly you will need to cater for translating guile return values such
as lists or vectors into containers that Swift can work with, and vice
versa.
This is all pretty well documented in the C++ code mentioned above, but
it is not for the faint hearted.
Chris
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Difficulty integrating with Swift/Objective-C
2021-09-05 8:26 ` Taylan Kammer
2021-09-05 9:35 ` paul
@ 2021-09-06 10:21 ` paul
2021-09-06 13:11 ` Taylan Kammer
1 sibling, 1 reply; 10+ messages in thread
From: paul @ 2021-09-06 10:21 UTC (permalink / raw)
To: Taylan Kammer, guile-user
Hello again list, Taylan,
On 2021-09-05 at 18:26 AEST, quoth Taylan Kammer
<taylan.kammer@gmail.com>:
> To narrow down the issue, I'd attempt a few things, in order:
>
> 1. Compile only the C code, adding a main() function, just to
> make sure the OS
> and the chosen Guile version and such are working fine with
> each other.
>
> 2. Compile pure Objective-C code, calling that run_guile()
> function firstly
> directly from the main() function in main.m of the
> Objective-C program, and
> commenting out the NSApplicationMain() call that would
> initialize Apple's
> application framework.
>
> 3. See if reactivating the NSApplicationMain() call causes
> problems. (It should
> be called *after* the Guile initialization.)
>
> 4. See if you can use Guile's C functions from
> -applicationDidFinishLaunching:
> e.g. by doing: scm_c_eval_string("(begin (display
> 'HelloWorld) (newline))")
>
> If that works, we now have an Objective-C + Guile application,
> and want to move
> to using Swift instead. This is where my Apple knowledge hits
> its limits because
> I never used Swift. :-)
>
> But I guess Swift should have something equivalent to the main()
> function of C and
> Objective-C, and calling Guile initialization from there might
> do the trick.
Thank you very much for your tips. I was actually able to unstick
myself with your suggestions: first i created a blank Objective-C
CLI app and integrated Guile, that worked well! Next i created a
new, blank, Objective-C AppKit GUI app. The same procedure worked
well there, too.
The more challenging bit was learning how to take my existing
Swift app and (re-)introduce a main() in Objective-C. Because it
turns out that Swift has some conveniences that cause it to
autogenerate a _main symbol behind-the-scenes. In any case you
can turn that off and create an Objective-C main function (my
project didn't have Objective-C to start with, but it was enough
to create a new file with a main() copied from my earlier
from-scratch experiments) which - long story short - i was able to
modify and get Guile booting correctly! I was even able to
complete step 4, to my surprise (sort of), and call
scm_c_eval_string straight from my Application Kit code. This
takes a bit of fiddling (Apple's so-called Precompiled Bridging
Header) to make Swift aware of C-land functions, but my app
actually already has a Rust-based core which i call out to with
this mechanism so here i was on firmer ground.
I think there must have been something weird about the state of my
project last night, because initially i was still having the
EXC_BAD_ACCESS issues, but making a new branch off my main and
doing the above worked well.
It should be said that i still couldn't use the Homebrew-packaged
version of Guile because of the JIT errors i described elsewhere,
but this isn't a blocker because i'm able to compile my own
libguile with `--enable-jit=no`.
Thanks again, i spent all weekend messing with this and couldn't
figure it out, your input was super useful.
All the best,
p.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Difficulty integrating with Swift/Objective-C
2021-09-05 10:56 ` Chris Vine
@ 2021-09-06 10:26 ` paul
2021-09-06 16:28 ` Chris Vine
0 siblings, 1 reply; 10+ messages in thread
From: paul @ 2021-09-06 10:26 UTC (permalink / raw)
To: Chris Vine, guile-user
Hey Chris,
On 2021-09-05 at 20:56 AEST, quoth Chris Vine
<vine35792468@gmail.com>:
> You appear to want to run scheme code as an extension language,
> via the
> guile VM, in a program written for MacOS in the Swift language.
This is exactly right.
> I know
> nothing about the Swift language and whether it has a sufficient
> C-like
> FFI to achieve this, but you may get some inspiration from the
> following, which enables scheme code to be run as an extension
> language
> within a C++ program:
> https://sourceforge.net/p/cxx-gtk-utils/git/ci/master/tree/c++-gtk-utils/extension.h
>
> However there are various issues. First, guile's exceptions
> (based on C's longjmp()/setjmp() and cognates) are almost
> certainly
> not implemented in the same way as Swift's exceptions (assuming
> Swift
> has exceptions), which means amongst other things that, if Swift
> has
> something akin to destructors/deinitialization, you should not
> allow
> guile exceptions to leave Swift objects undestroyed were guile
> to
> jump out of local scope on raising an exception
> (scm_dynwind_begin(),
> scm_dynwind_end and scm_dynwind_unwind_handler can be useful
> here if
> you are able to manage your Swift objects manually in C). Nor
> more
> generally should you allow Swift exceptions (if Swift has them)
> to
> escape out of a guile scm_dynwind_begin()/scm_dynwind_end()
> pair, or
> you will stop guile's resource management working correctly.
>
> Secondly, there are some issues relating to the fact that
> guile's
> 'make-fresh-user-module' and 'load' procedures leak memory,
> which can
> be problematic if all tasks run as scheme code are not to share
> the
> same top level.
>
> Thirdly you will need to cater for translating guile return
> values such
> as lists or vectors into containers that Swift can work with,
> and vice
> versa.
>
> This is all pretty well documented in the C++ code mentioned
> above, but
> it is not for the faint hearted.
I'll definitely take a look at the codebase you link; thank you.
Although i am probably on the fainter-hearted side, i have a bit
of hope it might be feasible, since my project actually already
includes a "core" implemented in Rust and included as a
statically-linked library. I'm able to call out to Rust functions
i've marked as `extern C`, and so while i don't fully understand
the mechanism and the implications for threading and exceptions,
so far it has worked well in that limited case. I'm hoping that i
can make something similar work in Guile. I think my needs are
fairly modest - initially my ambition is to allow the user to
rebind shortcut keys of my app using a Guile script. We'll see
what else i can come up with later.
Thanks for the info though, i'll definitely refer back if i run
into issues!
Kind regards,
p.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Difficulty integrating with Swift/Objective-C
2021-09-06 10:21 ` paul
@ 2021-09-06 13:11 ` Taylan Kammer
0 siblings, 0 replies; 10+ messages in thread
From: Taylan Kammer @ 2021-09-06 13:11 UTC (permalink / raw)
To: paul, guile-user
On 06.09.2021 12:21, paul wrote:
> Hello again list, Taylan,
>
> On 2021-09-05 at 18:26 AEST, quoth Taylan Kammer <taylan.kammer@gmail.com>:
>> To narrow down the issue, I'd attempt a few things, in order:
>>
>> 1. Compile only the C code, adding a main() function, just to make sure the OS
>> and the chosen Guile version and such are working fine with each other.
>>
>> 2. Compile pure Objective-C code, calling that run_guile() function firstly
>> directly from the main() function in main.m of the Objective-C program, and
>> commenting out the NSApplicationMain() call that would initialize Apple's
>> application framework.
>>
>> 3. See if reactivating the NSApplicationMain() call causes problems. (It should
>> be called *after* the Guile initialization.)
>>
>> 4. See if you can use Guile's C functions from -applicationDidFinishLaunching:
>> e.g. by doing: scm_c_eval_string("(begin (display 'HelloWorld) (newline))")
>>
>> If that works, we now have an Objective-C + Guile application, and want to move
>> to using Swift instead. This is where my Apple knowledge hits its limits because
>> I never used Swift. :-)
>>
>> But I guess Swift should have something equivalent to the main() function of C and
>> Objective-C, and calling Guile initialization from there might do the trick.
>
> Thank you very much for your tips. I was actually able to unstick myself with your suggestions: first i created a blank Objective-C CLI app and integrated Guile, that worked well! Next i created a new, blank, Objective-C AppKit GUI app. The same procedure worked well there, too.
>
> The more challenging bit was learning how to take my existing Swift app and (re-)introduce a main() in Objective-C. Because it turns out that Swift has some conveniences that cause it to autogenerate a _main symbol behind-the-scenes. In any case you can turn that off and create an Objective-C main function (my project didn't have Objective-C to start with, but it was enough to create a new file with a main() copied from my earlier from-scratch experiments) which - long story short - i was able to modify and get Guile booting correctly! I was even able to complete step 4, to my surprise (sort of), and call scm_c_eval_string straight from my Application Kit code. This takes a bit of fiddling (Apple's so-called Precompiled Bridging Header) to make Swift aware of C-land functions, bu
t my app actually already has a Rust-based core which i call out to with this mechanism so here i was on firmer ground.
>
> I think there must have been something weird about the state of my project last night, because initially i was still having the EXC_BAD_ACCESS issues, but making a new branch off my main and doing the above worked well.
>
> It should be said that i still couldn't use the Homebrew-packaged version of Guile because of the JIT errors i described elsewhere, but this isn't a blocker because i'm able to compile my own libguile with `--enable-jit=no`.
>
> Thanks again, i spent all weekend messing with this and couldn't figure it out, your input was super useful.
>
> All the best,
> p.
I'm happy to hear it worked, and thanks for reporting back. :-)
Personally I don't do any Apple-related development these days but it's
good to know what does and doesn't work.
--
Taylan
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Difficulty integrating with Swift/Objective-C
2021-09-06 10:26 ` paul
@ 2021-09-06 16:28 ` Chris Vine
0 siblings, 0 replies; 10+ messages in thread
From: Chris Vine @ 2021-09-06 16:28 UTC (permalink / raw)
To: guile-user
On Mon, 06 Sep 2021 20:26:53 +1000
paul <paul@inktvis.org> wrote:
> Hey Chris,
>
> On 2021-09-05 at 20:56 AEST, quoth Chris Vine
> <vine35792468@gmail.com>:
> > You appear to want to run scheme code as an extension language,
> > via the
> > guile VM, in a program written for MacOS in the Swift language.
>
> This is exactly right.
>
> > I know
> > nothing about the Swift language and whether it has a sufficient
> > C-like
> > FFI to achieve this, but you may get some inspiration from the
> > following, which enables scheme code to be run as an extension
> > language
> > within a C++ program:
> > https://sourceforge.net/p/cxx-gtk-utils/git/ci/master/tree/c++-gtk-utils/extension.h
> >
> > However there are various issues. First, guile's exceptions
> > (based on C's longjmp()/setjmp() and cognates) are almost
> > certainly
> > not implemented in the same way as Swift's exceptions (assuming
> > Swift
> > has exceptions), which means amongst other things that, if Swift
> > has
> > something akin to destructors/deinitialization, you should not
> > allow
> > guile exceptions to leave Swift objects undestroyed were guile
> > to
> > jump out of local scope on raising an exception
> > (scm_dynwind_begin(),
> > scm_dynwind_end and scm_dynwind_unwind_handler can be useful
> > here if
> > you are able to manage your Swift objects manually in C). Nor
> > more
> > generally should you allow Swift exceptions (if Swift has them)
> > to
> > escape out of a guile scm_dynwind_begin()/scm_dynwind_end()
> > pair, or
> > you will stop guile's resource management working correctly.
> >
> > Secondly, there are some issues relating to the fact that
> > guile's
> > 'make-fresh-user-module' and 'load' procedures leak memory,
> > which can
> > be problematic if all tasks run as scheme code are not to share
> > the
> > same top level.
> >
> > Thirdly you will need to cater for translating guile return
> > values such
> > as lists or vectors into containers that Swift can work with,
> > and vice
> > versa.
> >
> > This is all pretty well documented in the C++ code mentioned
> > above, but
> > it is not for the faint hearted.
>
> I'll definitely take a look at the codebase you link; thank you.
> Although i am probably on the fainter-hearted side, i have a bit
> of hope it might be feasible, since my project actually already
> includes a "core" implemented in Rust and included as a
> statically-linked library. I'm able to call out to Rust functions
> i've marked as `extern C`, and so while i don't fully understand
> the mechanism and the implications for threading and exceptions,
> so far it has worked well in that limited case. I'm hoping that i
> can make something similar work in Guile. I think my needs are
> fairly modest - initially my ambition is to allow the user to
> rebind shortcut keys of my app using a Guile script. We'll see
> what else i can come up with later.
>
> Thanks for the info though, i'll definitely refer back if i run
> into issues!
If you cut the code that I referred to down to its bare essentials, it
does what I think you have now arrived at yourself: calling
scm_eval_string() (in that code's case, actually
scm_eval_string_in_module()), via scm_with_guile(). It is
scm_with_guile() which actuates the guile VM within your program and
under which your scheme code is evaluated. You don't need to (and
really shouldn't) execute another main() procedure within your program
to evaluate the scheme code, and doing that would make integrating it
with your Swift code much more difficult.
scm_with_guile() and scm_eval_string() will execute guile code within
your program as if it were any other C function. However the
complications arise when you try to interface the scheme value returned
by scm_eval_string (and so by scm_with_guile()) into your Swift code -
that is, convert SCM values to Swift values, or you need to deal with
guile or Swift exceptions. Obviously the first of those is less
relevant if you are only executing scheme code for its side effects.
There are also important issues to be aware of if you intend to execute
guile code in more than one thread or you don't want every task called
up by scm_with_guile() to share the same top level. Looking at the code
I posted should be useful for dealing with those issues.
But the essentials of what you are doing seems right.
Chris
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Difficulty integrating with Swift/Objective-C
2021-09-05 6:03 Difficulty integrating with Swift/Objective-C paul
2021-09-05 8:26 ` Taylan Kammer
2021-09-05 10:56 ` Chris Vine
@ 2021-09-08 23:59 ` paul
2021-09-28 20:22 ` Aleix Conchillo Flaqué
2 siblings, 1 reply; 10+ messages in thread
From: paul @ 2021-09-08 23:59 UTC (permalink / raw)
To: guile-user
I wanted to follow up about another thing:
On 2021-09-05 at 16:03 AEST, quoth paul <paul@inktvis.org>:
> I had some difficulty getting my app to compile against Guile,
> but i eventually managed to link against a version of Guile
> installed with Homebrew (guile: stable 3.0.7 (bottled)), however
> when trying to boot it up i seemed to run into the same issue
> described by Jeffrey Walton [1]. My app would boot, and as soon
> as it hit the Guile initialisation calls, it would error out as
> follows:
>
> allocating JIT code buffer failed: Permission denied
> jit.c:5873: fatal: assertion failed
>
> While the other person seems to imply the problem is with
> Apple's M1 silicon, i'm actually running an older machine (2.9
> GHz Dual-Core Intel Core i5, macOS 11.5.2). I then managed to
> get further by downloading the Guile release tarball version
> 3.0.7 and and building with `./configure --enable-jit=no`;>
>
> [...]
>
> 1. https://mail.gnu.org/archive/html/bug-guile/2021-03/msg00012.html
It turned out that the JIT issue was _also_ PEBKAC i am glad to
report. Completely by accident i happened upon some settings in
the Xcode project of my app, under the Target > Signing &
Capabilities > Hardened Runtime options. One has to enable the
following two items:
* Allow execution of JIT-compiled code
* Allow unsigned executable memory
Those two settings correspond to entries in the
<myapp>.entitlements file as follows:
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
</dict>
Now, the app is able to build and run successfully against the
Homebrew-packaged version of Guile - super convenient!
I thought i'd post my findings in case someone else hits these
issues in the future. Or should i contribute a section to a
README somewhere, so that folks don't have to laboriously work
this out for themselves every time?
Cheers,
p.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Difficulty integrating with Swift/Objective-C
2021-09-08 23:59 ` paul
@ 2021-09-28 20:22 ` Aleix Conchillo Flaqué
0 siblings, 0 replies; 10+ messages in thread
From: Aleix Conchillo Flaqué @ 2021-09-28 20:22 UTC (permalink / raw)
To: paul; +Cc: guile-user
On Wed, Sep 8, 2021 at 4:59 PM paul <paul@inktvis.org> wrote:
>
> Now, the app is able to build and run successfully against the
> Homebrew-packaged version of Guile - super convenient!
>
Cool! Now that you have solved this issue I wonder if you can use
libraries from:
https://github.com/aconchillo/homebrew-guile
I believe setting the environment variables should be enough.
> I thought i'd post my findings in case someone else hits these
> issues in the future.
Definitely, thank you!
Aleix
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2021-09-28 20:22 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-09-05 6:03 Difficulty integrating with Swift/Objective-C paul
2021-09-05 8:26 ` Taylan Kammer
2021-09-05 9:35 ` paul
2021-09-06 10:21 ` paul
2021-09-06 13:11 ` Taylan Kammer
2021-09-05 10:56 ` Chris Vine
2021-09-06 10:26 ` paul
2021-09-06 16:28 ` Chris Vine
2021-09-08 23:59 ` paul
2021-09-28 20:22 ` Aleix Conchillo Flaqué
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).