From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Dimitris Papavasiliou Newsgroups: gmane.lisp.guile.user Subject: Need help embedding Guile Date: Tue, 21 Dec 2021 11:12:54 +0000 Message-ID: Reply-To: Dimitris Papavasiliou Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="8776"; mail-complaints-to="usenet@ciao.gmane.io" To: "guile-user@gnu.org" Original-X-From: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Tue Dec 21 12:15:57 2021 Return-path: Envelope-to: guile-user@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mzd7a-0001xM-Hm for guile-user@m.gmane-mx.org; Tue, 21 Dec 2021 12:15:54 +0100 Original-Received: from localhost ([::1]:51202 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mzd7Y-0006h6-Mq for guile-user@m.gmane-mx.org; Tue, 21 Dec 2021 06:15:52 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:46112) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mzd4z-0004vo-KZ for guile-user@gnu.org; Tue, 21 Dec 2021 06:13:13 -0500 Original-Received: from mail-40134.protonmail.ch ([185.70.40.134]:60629) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mzd4x-0005ya-44 for guile-user@gnu.org; Tue, 21 Dec 2021 06:13:13 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.ch; s=protonmail2; t=1640085176; bh=P5bJKBuhq6LjgZFPMDXUHLJ7j7VdIpWDBA0i6/70S3c=; h=Date:To:From:Reply-To:Subject:Message-ID:From:To:Cc; b=ALXIiEhnuYM4468nMDtA2Ff1Um+6EwPdwq4wcCc/oyOtB8x9jns8fMWKLpFk8sXWS XkeuwmxtWTgcl+78YN0Mc3sffh9oTMMkxqPEmnB6meAcIcfUqPyorH8kpRNMjFRMHp 5KIK0lubdTEhYMEIoZbe8sjnpQyvx10RMx9R/rm1r+qC1GaKi75BAs7dsHM/w4Bd/1 rfwVZ8dRNTU7o4HW+0V3H49lAlR8RCC1tlaXqvjYk75igM9SBe1h6xBg+FM6/h4j7b cDGUQ1T8CnAJh/J4ZoULQ3goZtIFE3dp2sgKsWmNRzyLDdfmCGDvXj/JpUi4rUc/Of O6jGijzU/VniQ== Received-SPF: pass client-ip=185.70.40.134; envelope-from=dpapavas@protonmail.ch; helo=mail-40134.protonmail.ch X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Original-Sender: "guile-user" Xref: news.gmane.io gmane.lisp.guile.user:17893 Archived-At: Hi all, I'm in the process of embedding Guile in an application and although I seem= to have the essentials working, I'd appreciate some confirmation of the validi= ty of my approach and also some tips on a couple of loose ends. I won't bore you with the specifics of my application; for the purposes of = the discussion, its most important characteristic, is that it uses Guile as a frontend of sorts. By this, I mean that a Scheme program is executed, whic= h creates objects in the C (well actually, and out of necessity, C++) domain. These objects represent geometric operations, in the form of a graph and ar= e evaluated once the Scheme program has terminated. Since the evaluation can= take a long time and the Scheme code itself, in simply creating nodes in the gra= ph, is expected to run to completion quite quickly, even though it can be conceptually complex, the emphasis on the Scheme side is on debugability in= stead of efficiency. My aim, is to be able to load a Scheme program from a file, run it to have = the graph created and then clean up. On error, I'd like to print out diagnosti= c information in the form of an error message with as accurate as possible so= urce location and a stack trace. (I'd also like to print the latter with my own formatting to match rest of the output of the application.) Although perhaps other approaches are possible, I have, for now, chosen to = leave memory management to the C++ side, so that my foreign objects need custom finalization. The basic layout of my current implementation, with unintere= sting portions left out, is the following (where `run_scheme' is called by the ma= in program to run a Scheme script): struct context { char *input, **first, **last; }; int run_scheme(const char *input, char **first, char **last) { struct context context =3D {const_cast(input), first, last}; scm_with_guile(&run_scheme_from_guile, &context); return 0; } static void *run_scheme_from_guile(void *data) { struct context *context =3D static_cast(data); scm_set_automatic_finalization_enabled(0); // Define some foreign objects types and subroutines. // [...] scm_set_program_arguments( context->last - context->first, context->first, context->input); scm_c_catch(SCM_BOOL_T, run_body, reinterpret_cast(context), post_handler, nullptr, pre_handler, nullptr); scm_gc(); scm_run_finalizers(); return nullptr; } static SCM run_body(void *data) { struct context *context =3D static_cast(data); scm_primitive_eval( =09scm_list_2( =09 scm_from_latin1_symbol("load"), =09 scm_from_latin1_string(context->input))); return SCM_UNSPECIFIED; } static SCM pre_handler(void *data, SCM key, SCM args) { SCM s =3D scm_make_stack(SCM_BOOL_T, SCM_EOL); SCM p =3D scm_current_error_port(); scm_print_exception(p, SCM_BOOL_F, key, args); scm_display_backtrace(s, p, SCM_BOOL_F, SCM_BOOL_F); return SCM_BOOL_T; } static SCM post_handler(void *data, SCM key, SCM args) { return SCM_BOOL_T; } Actually, my code in `pre_handler' is not quite what is shown above, as I p= rint the stack with my own formatting, but let's leave that for later. As I sai= d, this seems to be working, but certain points are unclear to me after readin= g all the documentation I could find and snooping around in Guile's source code: 1. The manual is not very specific about how and when finalizers are run. = The approach above seems to correctly finalize all objects created as the Sc= heme code executes, but if references are kept, say via (define), they are no= t finalized and I get memory leaks. Is there some way to arrange for the complete deinitialization of Guile after I've finished evaluating Scheme= code and making sure that all finalizers are run? 2. If, in `run_body', I simply do scm_c_primitive_load(context->input); then the code is evaluated, but on error I get no locations in the stack trace. The error is said to have occurred "in an unknown file" with no = line numbers. Evaluating `load' as shown above, seems to produce proper sour= ce locations in the stack trace. Is there something else I should be prefe= rably doing? 3. More generally, is there a preferable way to go about embedding Guile fo= r my use case? Thanks in advance for any pointers, Dimitris