mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-26 19:00:18 -06:00
9261c867b5
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2135 57a11ea4-9604-0410-9ed3-97b8803252fd
117 lines
4.9 KiB
Plaintext
117 lines
4.9 KiB
Plaintext
-*-text-*-
|
|
|
|
This file is intended to contain information for those interested in
|
|
working on the guile bits of GnuCash.
|
|
|
|
I've recently added some GUI functions callable from scheme. This is
|
|
generally pretty straightforward, and you can look in the code to see
|
|
how I did it, but there are a few bits you have to be careful about.
|
|
|
|
One of the main sources of useful information is "info guile-ref".
|
|
This contains the documentation for all the guile C-side functions
|
|
like gh_car(), gh_append(), etc. that manipulate opaque SCM objects
|
|
from the guile side.
|
|
|
|
Given that and a reasonable understanding of GTK/GNOME, you should be
|
|
able to follow what I've done.
|
|
|
|
Introduction To Scheme and guile(rgmerk)
|
|
--------------------------------
|
|
Please skip this if you already know what Scheme is and why it's
|
|
so cool . . .
|
|
|
|
Scheme is a dialect of LISP (List Programming), one of the earliest
|
|
programming languages. It makes so many things easy it's just not
|
|
funny. It can be a little confusing for people raised on C and Java,
|
|
but any time taken to learn it is made up for with easier-to-write,
|
|
easier-to-debug, more reusable, and more robust code.
|
|
|
|
Guile is an implementation of standard Scheme which is easily
|
|
embeddable in C, making multi-language development relatively
|
|
straightforward. You can easily access data and procedures from
|
|
either end. Guile supports a superset of R4RS (the Scheme standard).
|
|
For initial experimentation, you can use Guile as an interactive Scheme
|
|
shell to play around with the system.
|
|
|
|
SLIB is a a library for Scheme implementations (including guile)
|
|
that implements a large collection of useful data structures
|
|
and algorithms.
|
|
|
|
FIXME: Starting gnucash as a guile shell. ..
|
|
|
|
While the Guile documentation (in info format) explains
|
|
Guile specifics, it doesn't have much information about Scheme,
|
|
the language. The Internet Scheme Repository:
|
|
|
|
http://www.cs.indiana.edu/scheme-repository/home.html
|
|
|
|
has quite a useful collection of information, including
|
|
FAQs, online copies of the Scheme standard (which is actually
|
|
quite readable and useful), and pointers to web tutorials
|
|
and other resources.
|
|
|
|
g-wrap
|
|
------
|
|
|
|
g-wrap is the tool used to automate the wrapping of C functions
|
|
to make them callable from the guile code. Gnucash installs
|
|
its own local copy of g-wrap. Documentation in info format
|
|
is available in gnucash/lib/g-wrap/doc/g-wrap.info. Available
|
|
C functions are wrapped in gnucash/src/g-wrap/gnc.gwp. Pointers
|
|
are wrapped using some stuff in gnucash/lib/g-wrap/guile/pointer.scm
|
|
which is not documented but looks reasonably straightforward.
|
|
|
|
|
|
Garbage collection:
|
|
-------------------
|
|
|
|
One issue to keep in mind is that of garbage collection. You cannot
|
|
pass a scheme side item to the C side (through a SCM) and then store
|
|
that object off somewhere on the C side such that it lives longer than
|
|
all of it's guile side references. If you do, you're likely to get a
|
|
crash. The problem is that guile's garbage collector only knows to
|
|
save guile items that still have guile side pointers, or that are
|
|
found somewhere on the current C side stack. If you store a SCM item
|
|
off in a C data structure (say a callback pointer), and then return to
|
|
the guile side and drop the guile-side reference to the item, guile
|
|
may garbage collect it before it's used by the C side.
|
|
|
|
For example, this psudeo-code is a problem:
|
|
|
|
void gnc_some_function(SCM scm_thunk) {
|
|
gnc_set_push_button_callback(some_button, scm_thunk);
|
|
}
|
|
|
|
(define (unsafe-guile-function)
|
|
(let ((my-callback (lambda () (display "Hello\n"))))
|
|
(gnc:some-function my-callback)))
|
|
|
|
The problem here is that if you call unsafe-guile-function, it
|
|
registers the pointer to the anonymous lambda created in the let
|
|
construct with the button on the C-side and then returns. As soon as
|
|
it returns, guile has no more references to the anonymous lambda, and
|
|
it's not on the C stack, so guile thinks it's OK to garbage collect
|
|
the function even though the C side has a pointer to it and may still
|
|
use it.
|
|
|
|
The moral of this story is that if you need to have the C side ferret
|
|
away a scheme item for later, you must also keep at least one
|
|
reference to that item on the guile side until the C side is finished
|
|
with it. I believe that the guile people have recently come up with a
|
|
nice general solution to this problem, but until that's generally
|
|
available, there are a number of ways you can solve this.
|
|
|
|
If nothing else, you can just create a global hash on the guile side,
|
|
place the object in question in the hash table, and then have the
|
|
C-side delete that item from the hash when it's finished with it.
|
|
|
|
|
|
Guile Interrupts:
|
|
-----------------
|
|
|
|
Another issue that I'm not quite sure of myself yet is that of
|
|
interrupts. Guile has the ability to protect certain segments of code
|
|
with SCM_DEFER_INTS/SCM_ALLOW_INTS, but at the moment I'm not sure
|
|
when this is required. If anyone gets the chance to check this out
|
|
before I do, then please edit this file and put your findings here.
|