1 | Date: Mon, 14 Feb 2000 13:31:51 GMT |
---|
2 | From: John Harper <john@dcs.warwick.ac.uk> |
---|
3 | To: "Mikolaj J. Habryn" <dichro-mail-766da09@rcpt.to> |
---|
4 | Subject: Re: embedding librep |
---|
5 | |
---|
6 | Mikolaj J. Habryn writes: |
---|
7 | | Hmm - I'm having trouble reaching sourceforge at the moment, but |
---|
8 | |I'll dig through the archives and subscribe as soon as that changes. |
---|
9 | |
---|
10 | well, there's not much there, but there may be a few useful messages.. |
---|
11 | |
---|
12 | | |
---|
13 | | It appears that rep_load_environment does the actual execution of |
---|
14 | |the code - I presume that what I want to do is register lambda |
---|
15 | |expressions inside there (calling back into the C-code to do so), and |
---|
16 | |then return into inner_main. |
---|
17 | |
---|
18 | rep_load_environment is usually just used to do initialisation, in the |
---|
19 | case of rep.c it's the whole program, but that's not usual. Sawmill |
---|
20 | main.c is probably a better example, it's inner_main does the |
---|
21 | following: |
---|
22 | |
---|
23 | static repv |
---|
24 | inner_main (repv arg) |
---|
25 | { |
---|
26 | repv res = rep_load_environment(rep_string_dup ("sawmill")); |
---|
27 | if (res != rep_NULL) |
---|
28 | { |
---|
29 | /* final initialisation.. */ |
---|
30 | if(rep_SYM(Qbatch_mode)->value == Qnil) |
---|
31 | manage_windows (); |
---|
32 | |
---|
33 | /* then jump into the event loop.. */ |
---|
34 | if(rep_SYM(Qbatch_mode)->value == Qnil) |
---|
35 | res = Frecursive_edit (); |
---|
36 | } |
---|
37 | return res; |
---|
38 | } |
---|
39 | |
---|
40 | this is called after all exported lisp functions have been registered. |
---|
41 | manage_windows is a function to adopt all existing top-level windows, |
---|
42 | Frecursive_edit is rep's built-in event loop (you use |
---|
43 | rep_register_input_fd to register a function to be called when data |
---|
44 | arrives on a particular fd, e.g. sawmill's X connection) |
---|
45 | |
---|
46 | after this function exits, so will sawmill |
---|
47 | |
---|
48 | | |
---|
49 | | How do I make a C function visible to the lisp code, to register the |
---|
50 | |hooks with, and so that the hooks can get extra information if they |
---|
51 | |need it? |
---|
52 | |
---|
53 | by convention a lisp function `foo-bar' is represented by a C function |
---|
54 | Ffoo_bar and a subroutine data object Sfoo_bar. These are defined using |
---|
55 | the DEFUN macro: |
---|
56 | |
---|
57 | DEFUN ("foo-bar", Ffoo_bar, Sfoo_bar, (repv arg1), rep_Subr1) |
---|
58 | { |
---|
59 | /* signal an error if `arg1' isn't a cons */ |
---|
60 | rep_DECLARE (1, arg1, rep_CONSP (arg1)); |
---|
61 | |
---|
62 | ... do something with arg |
---|
63 | |
---|
64 | return some-result-repv; |
---|
65 | } |
---|
66 | |
---|
67 | (repv arg1) is the actual argument list for the function, rep_Subr1 |
---|
68 | defines the type of the subroutine object, in this case a function |
---|
69 | receiving a single argument, there's rep_Subr[1-5] and rep_SubrN which |
---|
70 | takes a single parameter, the _list_ of arguments given to the function |
---|
71 | |
---|
72 | to register this function with the interpreter it's necessary to then |
---|
73 | call: |
---|
74 | rep_ADD_SUBR (Sfoo_bar); |
---|
75 | |
---|
76 | in an initialisation function somewhere. |
---|
77 | |
---|
78 | | |
---|
79 | | How do I actually call the hooks, once they've been registered with |
---|
80 | |the C code? |
---|
81 | |
---|
82 | DEFUN-declared functions can be called as normal C functions. To create |
---|
83 | a hook, you need to define a symbol, i.e.: |
---|
84 | |
---|
85 | DEFSYM (foo_bar, "foo-bar"); |
---|
86 | |
---|
87 | this sets up storage for a symbol `foo-bar', and creates a `repv Qfoo_bar' |
---|
88 | variable. You then need to call |
---|
89 | |
---|
90 | rep_INTERN (foo_bar); |
---|
91 | |
---|
92 | in an initialisation function to initialise `Qfoo_bar'. If the symbol |
---|
93 | needs dynamic scope (i.e. it's used to represent a hook), then you do: |
---|
94 | |
---|
95 | rep_INTERN_SPECIAL (foo_bar); |
---|
96 | |
---|
97 | you can then do for example: |
---|
98 | |
---|
99 | Fset (Qfoo_bar, Qnil); |
---|
100 | |
---|
101 | to initialise it to nil, though that's not actually required for hooks. |
---|
102 | |
---|
103 | To invoke a hook, use Fcall_hook, i.e. |
---|
104 | |
---|
105 | Fcall_hook (Qfoo_bar, ARG-LIST, TYPE) |
---|
106 | |
---|
107 | ARG-LIST is the list of argument values to pass to the hook, e.g. to |
---|
108 | pass a single value use `rep_LIST_1 (VALUE)'. TYPE is a symbol defining |
---|
109 | how to interpret the values returned by functions, usually just use |
---|
110 | Qnil to force all functions in the hook to be called. |
---|
111 | |
---|
112 | If you just want to call a single lisp function, you can use |
---|
113 | rep_call_lispN, for example: |
---|
114 | |
---|
115 | rep_call_lisp1 (Fsymbol_value (Qfoo_bar, Qt), VALUE); |
---|
116 | |
---|
117 | when you do anything that may execute lisp code, you need to careful |
---|
118 | about garbage collection. Basically, you must have told the interpreter |
---|
119 | about any lisp values you're going to use after the called lisp code |
---|
120 | finishes executing. |
---|
121 | |
---|
122 | John |
---|
123 | |
---|