OSDN Git Service

【更新内容】
[ring-lang-081/ring.git] / docs / en / target / ringemb.txt
1 .. index:: 
2         single: Embedding Ring in Ring; Embedding Ring in Ring
3
4 ======================
5 Embedding Ring in Ring
6 ======================
7
8 In this chapter we will learn about embedding Ring in Ring programs and applications.
9
10 .. index:: 
11         pair: Embedding Ring in Ring; Embedding Ring in Ring without sharing the State
12
13 Embedding Ring in Ring without sharing the State
14 ================================================
15
16 From Ring 1.0 we already have functions for embedding Ring in the C language. Also we
17 can execute Ring code inside Ring programs using the eval() function. In this release
18 we provide functions for embedding Ring in Ring programs without sharing the state.
19
20 Advantages:
21
22 (1) Quick integration for Ring programs and applications together without conflicts.
23
24 (2) Execute and run Ring code in safe environments that we can trace.
25
26 Example:
27
28 .. code-block:: ring
29
30         pState = ring_state_init()
31         ring_state_runcode(pState,"See 'Hello, World!'+nl")
32         ring_state_runcode(pState,"x = 10")
33
34         pState2 = ring_state_init()
35         ring_state_runcode(pState2,"See 'Hello, World!'+nl")
36         ring_state_runcode(pState2,"x = 20")
37
38         ring_state_runcode(pState,"see x +nl")
39         ring_state_runcode(pState2,"see x +nl")
40
41         v1 = ring_state_findvar(pState,"x")
42         v2 = ring_state_findvar(pState2,"x")
43
44         see v1[3] + nl
45         see V2[3] + nl
46
47         ring_state_delete(pState)
48         ring_state_delete(pState2)
49
50 Output:
51
52 .. code-block:: ring
53
54         Hello, World!
55         Hello, World!
56         10
57         20
58         10
59         20
60
61 .. index:: 
62         pair: Embedding Ring in Ring; Serial Execution of Programs
63
64 Serial Execution of Programs
65 ============================
66
67 We can execute application after another application using ring_state_main()
68
69 Example:
70
71 .. code-block:: ring
72
73         chdir(exefolder()+"/../applications/formdesigner")
74         ring_state_main('formdesigner.ring')
75         chdir(exefolder()+"/../applications/cards")
76         ring_state_main('cards.ring')
77
78 .. index:: 
79         pair: Embedding Ring in Ring; ring_state_setvar()
80
81 ring_state_setvar()
82 ===================
83
84 Using ring_state_setvar() we can set variables value
85
86 The value could be (String, Number, List or C Pointer)
87
88 We need this function to quickly pass lists and C pointers to the Sub Ring Environment
89
90 Syntax:
91
92 .. code-block:: none
93
94         ring_state_setvar(oState,cVariableName,Value)
95
96 Example:
97
98 .. code-block:: ring
99
100         load "guilib.ring"
101
102         myapp   = null
103         win     = null
104
105         func main
106                 myapp = new qApp {
107                         win = new qWidget() {
108                                 setWindowTitle("Advanced Example on using ring_state_setvar()")
109                                 move(100,100)
110                                 resize(600,400)
111                                 new qPushButton(win) {
112                                         setText("Test")
113                                         setClickEvent("Test()")
114                                 }
115                                 # We need this because using load 'guilib.ring' in
116                                 # the sub environment
117                                 # Will create timers by Qt and closing the window 
118                                 # will not be enough to close the application
119                                 oFilter = new qAllEvents(win)
120                                 oFilter.setCloseEvent("myapp.quit()")
121                                 win.installeventfilter(oFilter)
122                                 show()
123                         }
124                         exec()
125                 }
126
127         func test
128                 pState = ring_state_init()
129                 ring_state_runcode(pstate,"load 'guilib.ring'")
130                 ring_state_runcode(pState,"x = NULL")
131                 # Pass String
132                         ring_state_setvar(pState,"x","hello")
133                         ring_state_runcode(pState,"? x")
134                 # Pass Number
135                         ring_state_setvar(pState,"x",100)
136                         ring_state_runcode(pState,"? x")
137                 # Pass List
138                         ring_state_setvar(pState,"x",["one","two","three"])
139                         ring_state_runcode(pState,"? x")
140                 # Pass Object
141                 # We can't pass the Ring Object (win)
142                 # Because Objects store pointers to the Class Information
143                 # And the class is related to the Parent Ring Environment
144                 # And the sub Ring environment can't access it
145                 # But we can pass C pointers like win.pObject
146                         ring_state_setvar(pState,"x",win.pObject)
147                 # Now we create the object again but using the same C pointer
148                 # So we have access to the Same window in the parent Ring enviroment
149                         ring_state_runcode(pState,"
150                                 new qWidget {
151                                         pObject = x
152                                         setwindowtitle('Message from the Sub Ring Environment')
153                                 }
154                         ")
155                 ring_state_delete(pState)
156
157
158 .. index:: 
159         pair: Embedding Ring in Ring; ring_state_new() and ring_state_mainfile()
160
161 ring_state_new() and ring_state_mainfile()
162 ==========================================
163
164 Using ring_state_new() and ring_state_mainfile() we can run Ring programs from Ring programs
165
166 But unlike ring_state_main(), Here we can control when to delete the Ring state!
167
168 This is important when we run GUI programs from GUI programs
169
170 Because they will share the GUI Library (RingQt), And In this case the caller will call
171
172 qApp.Exec()
173
174 So the sub program, will not stop and will return to the Main program
175
176 Here deleting the State of the sub programs will lead to a problem when we run the sub program events
177
178 So keeping the state is important for sub GUI programs hosted in GUI programs.
179
180 Example:
181
182 .. code-block:: ring
183
184         load "guilib.ring"
185
186         func main
187                 new qApp {
188                         win = new qWidget() {
189                                 setWindowTitle("Test ring_state_mainfile()")
190                                 resize(400,400) move(100,100)
191                                 btn = new qPushButton(Win) {
192                                         settext("test")
193                                         setclickevent("mytest()")
194                                 }
195                                 show()
196                         }
197                         exec()
198                 }
199
200         func mytest
201                 pState = ring_state_new()
202                 ring_state_mainfile(pState,"runprogram.ring")
203                 # Here we don't delete the state if we will run GUI application
204                 # So we can run the GUI application events 
205                         // ring_state_delete(pState)
206
207 If you will use this feature, remember to update the previous example based on your application needs
208
209 So you can call ring_state_delete() at some point to avoid the memory leak!
210
211 .. index:: 
212         pair: Embedding Ring in Ring; Runtime Errors when Embedding Ring in Ring
213
214 Runtime Errors when Embedding Ring in Ring
215 ==========================================
216
217 Starting from Ring 1.8 
218
219 When embedding Ring in Ring, the error in the hosted environment will not close the host
220
221 Example:
222
223 .. code-block:: ring
224
225         ? "Start the test!" 
226
227         pState = ring_state_init()
228
229         ring_state_runcode(pState," ? 'Let us try having an error' ? x")
230
231         ring_state_delete(pState)
232
233         ? ""
234         ? "End of test!"
235
236 Output:
237
238 .. code-block:: none
239
240         Start the test!
241         Let us try having an error
242
243         Line 1 Error (R24) : Using uninitialized variable : x
244         in file Ring_EmbeddedCode
245         End of test!
246
247 .. index:: 
248         pair: Embedding Ring in Ring; ring_state_filetokens() function
249
250 ring_state_filetokens() function
251 ================================
252
253 Starting from Ring 1.12 we have the ring_state_filetokens() function
254
255 Using this function we can get all the tokens in the ring source code file.
256
257 .. code-block:: ring
258
259         C_FILENAME      = "test_tokens.ring"
260         C_WIDTH         = 12
261
262         # write the file
263                 write(C_FILENAME,'
264                                 see "Hello, World!"
265                                 ? 3*2+3
266                                 Name = "Ring"
267                                 ? Name
268         ')
269
270         # Token Type
271                 C_KEYWORD       = 0
272                 C_OPERATOR      = 1
273                 C_LITERAL       = 2
274                 C_NUMBER        = 3
275                 C_IDENTIFIER    = 4
276                 C_ENDLINE       = 5
277
278         # Keywords List
279         aKEYWORDS = ["IF","TO","OR","AND","NOT","FOR","NEW","FUNC", 
280         "FROM","NEXT","LOAD","ELSE","SEE","WHILE","OK","CLASS","RETURN","BUT", 
281         "END","GIVE","BYE","EXIT","TRY","CATCH","DONE","SWITCH","ON","OTHER","OFF", 
282         "IN","LOOP","PACKAGE","IMPORT","PRIVATE","STEP","DO","AGAIN","CALL","ELSEIF", 
283         "PUT","GET","CASE","DEF","ENDFUNC","ENDCLASS","ENDPACKAGE", 
284         "CHANGERINGKEYWORD","CHANGERINGOPERATOR","LOADSYNTAX"]
285
286         pState = ring_state_new()
287         aList = ring_state_filetokens(pState,C_FILENAME)
288         PrintTokens(aList)
289         ring_state_delete(pState)
290
291         func PrintTokens aList
292                 for aToken in aList
293                         switch aToken[1]
294                         on C_KEYWORD 
295                                 ? Width("Keyword",C_WIDTH) + ": "  + aKeywords[0+aToken[2]]
296                         on C_OPERATOR 
297                                 ? Width("Operator",C_WIDTH)  + ": " + aToken[2]
298                         on C_LITERAL 
299                                 ? Width("Literal",C_WIDTH)  + ": " + aToken[2]
300                         on C_NUMBER 
301                                 ? Width("Number",C_WIDTH)  + ": " + aToken[2]
302                         on C_IDENTIFIER 
303                                 ? Width("Identifier",C_WIDTH)  + ": " + aToken[2]
304                         on C_ENDLINE 
305                                 ? "EndLine"
306                         other
307                                 
308                         off
309                 next
310
311         func Width cText,nWidth
312                 return cText+copy(" ",nWidth-len(cText))
313
314 Output:
315
316 .. code-block:: none
317
318         EndLine
319         Keyword     : SEE
320         Literal     : Hello, World!
321         EndLine
322         Operator    : ?
323         Number      : 3
324         Operator    : *
325         Number      : 2
326         Operator    : +
327         Number      : 3
328         EndLine
329         Identifier  : name
330         Operator    : =
331         Literal     : Ring
332         EndLine
333         Operator    : ?
334         Identifier  : name
335         EndLine