Creation of a new type for Scol » History » Version 3
ModularMix, 10/18/2011 10:27 AM
1 | 3 | ModularMix | h1. Creation of a new type for Scol |
---|---|---|---|
2 | 1 | ModularMix | |
3 | 2 | ModularMix | Similarly with Scol functions, it's also possible to extend Scol language by creating new data types using the integration of C/C++ plugins. |
4 | 1 | ModularMix | |
5 | 2 | ModularMix | h2. Definition of *Bloc* data type |
6 | 1 | ModularMix | |
7 | 2 | ModularMix | In this tutorial, we will create a basic data type which will store a name and an integer value. We'll also define the getters and setters for each of the properties. |
8 | As we will implement this new data type using a standard C++ class, we'll also define default constructor and destructor. |
||
9 | Now, let's create a new C++ header file named *Bloc.h*. Copy/paste the following explicit code into it : |
||
10 | 1 | ModularMix | <pre> |
11 | // Include providing MAX_PATH define |
||
12 | #include <windows.h> |
||
13 | |||
14 | /*! |
||
15 | * Bloc class. A simple class that has a name and a value associated with it. |
||
16 | * It allows simple operations like getting and setting its attributes. |
||
17 | * |
||
18 | **/ |
||
19 | class Bloc |
||
20 | { |
||
21 | private: |
||
22 | int value; //!< The value of the bloc |
||
23 | char name[MAX_PATH]; //!< The name of the bloc |
||
24 | |||
25 | public: |
||
26 | int getValue(); |
||
27 | char* getName(); |
||
28 | void setName(char*); |
||
29 | void setValue(int); |
||
30 | Bloc(void); |
||
31 | ~Bloc(void); |
||
32 | }; |
||
33 | </pre> |
||
34 | |||
35 | 2 | ModularMix | |
36 | Then, let's create the C++ source file (*Bloc.cpp*) in which we will implement the different functions. |
||
37 | The source code is still very explicit, our object will act as a property container that we can get or set using getters and setters. |
||
38 | 1 | ModularMix | <pre> |
39 | #include "Bloc.h" |
||
40 | #include <string.h> |
||
41 | #include <stdio.h> |
||
42 | |||
43 | /*! |
||
44 | * \brief Bloc constructor |
||
45 | * |
||
46 | */ |
||
47 | Bloc::Bloc(void) |
||
48 | { |
||
49 | value=0; |
||
50 | strcpy_s(name,"SuperBloc"); |
||
51 | } |
||
52 | |||
53 | /*! |
||
54 | * \brief Bloc destructor |
||
55 | * |
||
56 | */ |
||
57 | Bloc::~Bloc(void) |
||
58 | { |
||
59 | } |
||
60 | |||
61 | /*! |
||
62 | * \brief Gives the bloc value |
||
63 | * \return The bloc value |
||
64 | */ |
||
65 | int Bloc::getValue() |
||
66 | { |
||
67 | return value; |
||
68 | } |
||
69 | |||
70 | /*! |
||
71 | * \brief Gives the bloc name |
||
72 | * \return The bloc name |
||
73 | * |
||
74 | */ |
||
75 | char * Bloc::getName() |
||
76 | { |
||
77 | return name; |
||
78 | } |
||
79 | |||
80 | /*! |
||
81 | * \brief Set the bloc value |
||
82 | * \param myValue : The new value |
||
83 | */ |
||
84 | void Bloc::setValue(int myValue) |
||
85 | { |
||
86 | value = myValue; |
||
87 | } |
||
88 | |||
89 | /*! |
||
90 | * \brief Set the bloc name |
||
91 | * \param myValue : The new name |
||
92 | */ |
||
93 | void Bloc::setName(char* myName) |
||
94 | { |
||
95 | strncpy_s(name, myName, MAX_PATH-1); |
||
96 | } |
||
97 | 2 | ModularMix | </pre> |
98 | |||
99 | |||
100 | h2. Binding between C and Scol |
||
101 | |||
102 | Now we'll see how to be able to use *Bloc* object in Scol language, by integrating it into our plugin Template. |
||
103 | |||
104 | h3. Creation and destruction of *Bloc* object |
||
105 | |||
106 | The first step is to make available the definition of *Bloc* object in *template.cpp*, by including the file *Bloc.h* : |
||
107 | <pre> |
||
108 | #include "Bloc.h" |
||
109 | </pre> |
||
110 | |||
111 | |||
112 | *OBJBLOCSCOL* enables to store the unique ID linked to the new Scol type. This ID is allocated by Scol virtual machine during the registration of this new type (we will explain this later in this document). |
||
113 | <pre> |
||
114 | //! Bloc Object in Scol |
||
115 | int OBJBLOCSCOL; |
||
116 | |||
117 | //! BlocObj is set here as a type (an int) for doxygen documentation |
||
118 | typedef int BlocObj; |
||
119 | </pre> |
||
120 | |||
121 | The first function to be defined is the one which will allow to create the object and add it to the Scol stack. |
||
122 | This one will correspond to the followin Scol prototype : *fun [Chn] BlocObj*. We have to check that the first element on the Scol stack is a valid channel. |
||
123 | Once the input parameters have been checked, the creation of the *Bloc* object is done in two steps : |
||
124 | * The memory allocation ad the creation of the object in C++ |
||
125 | * The allocation of a space in Scol stack, and the call to the function *OBJcreate* which will create the object in Scol |
||
126 | <pre> |
||
127 | /*! @ingroup group1 |
||
128 | * \brief _CRbloc : Open, initialize Bloc object |
||
129 | * |
||
130 | * <b>Prototype:</b> fun [Chn] BlocObj |
||
131 | * |
||
132 | * \param Chn : current channel |
||
133 | * |
||
134 | * \return BlocObj : Bloc object if success, NIL otherwise |
||
135 | **/ |
||
136 | int _CRbloc(mmachine m) |
||
137 | { |
||
138 | #ifdef _SCOL_DEBUG_ |
||
139 | MMechostr(MSKDEBUG,"_CRbloc\n"); |
||
140 | #endif |
||
141 | |||
142 | // Declare local variables |
||
143 | int k = 0; |
||
144 | |||
145 | // Get the channel without pulling it (first element in the stack) |
||
146 | int channel = MMget(m, 0); |
||
147 | |||
148 | // Test the channel |
||
149 | if (channel == NIL) |
||
150 | { |
||
151 | MMechostr(MSKDEBUG, "Channel NIL\n"); |
||
152 | MMpull(m); // Pull the channel |
||
153 | MMpush(m, NIL); // Push NIL on the stack |
||
154 | return 0; |
||
155 | } |
||
156 | |||
157 | // Create bloc instance |
||
158 | Bloc * bloc = new Bloc(); |
||
159 | |||
160 | if (bloc == NULL) |
||
161 | { |
||
162 | MMechostr(MSKDEBUG, "_CRbloc ...initialization failed\n"); |
||
163 | SAFE_DELETE(bloc) ; |
||
164 | MMpull(m); // Pull the channel |
||
165 | MMpush(m, NIL); // Push NIL on the stack |
||
166 | return 0; |
||
167 | } |
||
168 | MMechostr(MSKDEBUG,"_CRbloc ...initialization successful\n"); |
||
169 | |||
170 | // Allocate a space in the stack for a table of bloc objects |
||
171 | int blocTab = MMmalloc(m, 1, TYPETAB); |
||
172 | if (blocTab == NIL) |
||
173 | { |
||
174 | MMechostr(MSKDEBUG,"_CRbloc ...MMmalloc failed\n"); |
||
175 | SAFE_DELETE(bloc); |
||
176 | MMpull(m); // Pull the channel |
||
177 | return MMpush(m, NIL); // Push NIL on the stack |
||
178 | } |
||
179 | MMechostr(MSKDEBUG,"_CRbloc ...MMmalloc successful\n"); |
||
180 | |||
181 | // Push the table of bloc objects into the stack |
||
182 | MMstore(m, blocTab, 0, (int)bloc); |
||
183 | MMpush(m, PTOM(blocTab)); |
||
184 | |||
185 | // Create a new scol bloc object |
||
186 | k = OBJcreate(m, OBJBLOCSCOL, (int)bloc, NULL, NULL); |
||
187 | MMechostr(MSKDEBUG,"_CRbloc ...object creation successful\n"); |
||
188 | |||
189 | #ifdef _SCOL_DEBUG_ |
||
190 | MMechostr(MSKDEBUG,"ok\n"); |
||
191 | #endif |
||
192 | |||
193 | // Return bloc object |
||
194 | return k; |
||
195 | } |
||
196 | </pre> |
||
197 | |||
198 | The second function to define is the one to destroy the object on a query made by the Scol developer. |
||
199 | The singularity of this function is that we don't pop from the Scol stack the object passed as a parameter, and we don't delete the associated C++ object either. |
||
200 | Instead of this, we use the Scol Garbage Collector (GC) using the function *OBJdelTM* from the Scol API. This function needs to know the Scol type of the object we want to delete. |
||
201 | <pre> |
||
202 | /*! @ingroup group1 |
||
203 | * \brief _DSbloc : Destroy bloc object |
||
204 | * |
||
205 | * <b>Prototype:</b> fun [BlocObj] I |
||
206 | * |
||
207 | * \param BlocObj : Bloc Object to destroy |
||
208 | * |
||
209 | * \return I : 0 if success, NIL otherwise |
||
210 | **/ |
||
211 | int _DSbloc(mmachine m) |
||
212 | { |
||
213 | #ifdef _SCOL_DEBUG_ |
||
214 | MMechostr(MSKDEBUG,"_DSbloc\n"); |
||
215 | #endif |
||
216 | |||
217 | int bloc = MTOP( MMget(m,0) ); |
||
218 | if ( bloc == NIL ) { MMset(m,0,NIL); return 0; } |
||
219 | |||
220 | OBJdelTM( m, OBJBLOCSCOL, PTOM(bloc) ); |
||
221 | MMset(m,0,0); |
||
222 | |||
223 | #ifdef _SCOL_DEBUG_ |
||
224 | MMechostr(MSKDEBUG,"ok\n"); |
||
225 | #endif |
||
226 | return 0; |
||
227 | } |
||
228 | </pre> |
||
229 | |||
230 | |||
231 | As previously stated, we have to define a callback function for the object destruction which will then be called by the GC. |
||
232 | This function will pop the object from the Scol stack and delete the C++ object from the memory. |
||
233 | <pre> |
||
234 | /*! |
||
235 | * \brief Scol object destroy callback |
||
236 | * |
||
237 | * \param mmachine : scol machine structure |
||
238 | * \param int : scol object system handle |
||
239 | * \param int : scol object stack handle |
||
240 | * |
||
241 | * \return int : 0 |
||
242 | **/ |
||
243 | int destroyBlocObj(mmachine m, int handsys, int blocTab) |
||
244 | { |
||
245 | // Read the first element of a TAB element (table of objects) |
||
246 | Bloc* bloc = (Bloc*) MMfetch(m, MTOP(blocTab), 0); |
||
247 | if (bloc == NULL) |
||
248 | { |
||
249 | // Write the first element in the stack, without pulling it |
||
250 | MMset(m, 0, NIL); |
||
251 | return 0; |
||
252 | } |
||
253 | |||
254 | // Safely dispose of "Bloc" pointer |
||
255 | SAFE_DELETE(bloc); |
||
256 | |||
257 | // Write the first element of a TAB element |
||
258 | MMstore(m, MTOP(blocTab), 0, NULL); |
||
259 | |||
260 | // Display debug message |
||
261 | MMechostr(MSKDEBUG,"Bloc object destroyed.\n"); |
||
262 | return 0; |
||
263 | } |
||
264 | </pre> |
||
265 | |||
266 | |||
267 | Given that all our functions are defined, we will register the new data type for Scol. |
||
268 | It's important to notice : |
||
269 | * the binding to the callback function for the object destruction (*destroyBlocObj*), |
||
270 | * the parameter "OBJBLOCSCOL" which corresponds to the type name as it will be used in a Scol program. |
||
271 | |||
272 | Finally, the function returns an ID for the new data type, which is stored in the global variable *OBJBLOCSCOL* (we remind that this variable is used in the function *_DSBloc* to notice to the GC the object type to delete). |
||
273 | <pre> |
||
274 | // Declare a new type of object ("OBJBLOCSCOL") |
||
275 | OBJBLOCSCOL = OBJregister(0 /*nb of callback*/, 1/* deleted from parent */, destroyBlocObj, "OBJBLOCSCOL"); |
||
276 | </pre> |
||
277 | |||
278 | |||
279 | The binding of the C++ functions enabling to create and delete a *Bloc* object in Scol is registered using *PKhardpak* function, so we have to modify the parameters of this function. |
||
280 | We notice the specific values used to bind the Scol data type, which name will be *ObjBloc*. |
||
281 | <pre> |
||
282 | //! Nb of Scol functions or types |
||
283 | #define NbTplPKG 4 |
||
284 | |||
285 | /*! |
||
286 | * Scol function names |
||
287 | **/ |
||
288 | char* TplName[NbTplPKG] = |
||
289 | { |
||
290 | "_HelloWorld", |
||
291 | "ObjBloc", |
||
292 | "_CRbloc", |
||
293 | "_DSbloc" |
||
294 | }; |
||
295 | |||
296 | /*! |
||
297 | * Pointers to C functions that manipulate the VM for each scol function previously defined |
||
298 | **/ |
||
299 | int (*TplFunc[NbTplPKG])(mmachine m)= |
||
300 | { |
||
301 | _HelloWorld, |
||
302 | NULL, |
||
303 | _CRbloc, |
||
304 | _DSbloc |
||
305 | }; |
||
306 | |||
307 | /*! |
||
308 | * Nb of arguments of each scol function |
||
309 | **/ |
||
310 | int TplNArg[NbTplPKG]= |
||
311 | { |
||
312 | 0, |
||
313 | TYPTYPE, |
||
314 | 1, |
||
315 | 1 |
||
316 | }; |
||
317 | |||
318 | /*! |
||
319 | * Prototypes of the scol functions |
||
320 | **/ |
||
321 | char* TplType[NbTplPKG]= |
||
322 | { |
||
323 | "fun [] I", // _HelloWorld |
||
324 | NULL, |
||
325 | "fun [Chn] ObjBloc", // _CRbloc |
||
326 | "fun [ObjBloc] I" // _DSbloc |
||
327 | }; |
||
328 | </pre> |
||
329 | |||
330 | h3. Access to the properties of Bloc object |
||
331 | |||
332 | To access the properties of *Bloc* object, we will define the getters and setters for each property of the object. |
||
333 | The important point here is to well observe and understand for each function the different operations updating the Scol stack, regarding the Scol prototype (retrieve Scol parameters, check all of them and return the appropriate Scol value). |
||
334 | <pre> |
||
335 | /*! @ingroup group1 |
||
336 | * \brief _GETblocValue : Get the value of the Bloc object |
||
337 | * |
||
338 | * <b>Prototype:</b> fun [BlocObj] I |
||
339 | * |
||
340 | * \param BlocObj : bloc object |
||
341 | * |
||
342 | * \return I : return bloc value, nil otherwise |
||
343 | **/ |
||
344 | int _GETblocValue(mmachine m) |
||
345 | { |
||
346 | #ifdef _SCOL_DEBUG_ |
||
347 | MMechostr(MSKDEBUG,"_GETblocValue\n"); |
||
348 | #endif |
||
349 | // Get bloc table from the stack, then transform it |
||
350 | int blocTable = MTOP( MMget(m,0) ) ; |
||
351 | if ( blocTable == NIL ) { MMset(m,0,NIL) ; return 0 ; } |
||
352 | |||
353 | // cast this bloc in a Bloc object |
||
354 | Bloc* bloc = (Bloc*)MMfetch(m, blocTable, 0) ; |
||
355 | if( !bloc ) { MMset(m,0,NIL) ; return 0 ; } |
||
356 | |||
357 | // put the return of the function call in the stack |
||
358 | MMset(m,0,ITOM(bloc->getValue())); |
||
359 | |||
360 | #ifdef _SCOL_DEBUG_ |
||
361 | MMechostr(MSKDEBUG,"ok\n"); |
||
362 | #endif |
||
363 | |||
364 | return 0; |
||
365 | } |
||
366 | |||
367 | /*! @ingroup group1 |
||
368 | * \brief _SETblocValue : Set the value of the bloc |
||
369 | * |
||
370 | * <b>Prototype:</b> fun [BlocObj I] I |
||
371 | * |
||
372 | * \param BlocObj : bloc object |
||
373 | * \param I : New value |
||
374 | * |
||
375 | * \return I : 0 if success, -1 otherwise |
||
376 | **/ |
||
377 | int _SETblocValue(mmachine m) |
||
378 | { |
||
379 | #ifdef _SCOL_DEBUG_ |
||
380 | MMechostr(MSKDEBUG,"_SETblocValue\n"); |
||
381 | #endif |
||
382 | // Get param |
||
383 | int value = MTOI( MMpull(m) ) ; |
||
384 | |||
385 | // Get Bloc table |
||
386 | int blocTable = MTOP( MMget(m,0) ) ; |
||
387 | if ( blocTable == NIL ) { MMset(m,0,-1) ; return 0 ; } |
||
388 | |||
389 | // Cast the content of bloc table to Bloc* |
||
390 | Bloc* bloc = (Bloc*)MMfetch(m, blocTable, 0) ; |
||
391 | bloc->setValue(value); |
||
392 | MMset(m,0,0); |
||
393 | |||
394 | #ifdef _SCOL_DEBUG_ |
||
395 | MMechostr(MSKDEBUG,"ok\n"); |
||
396 | #endif |
||
397 | |||
398 | return 0; |
||
399 | } |
||
400 | |||
401 | /*! @ingroup group1 |
||
402 | * \brief _GETblocName : Get the name of the bloc |
||
403 | * |
||
404 | * <b>Prototype:</b> fun [BlocObj] S |
||
405 | * |
||
406 | * \param BlocObj : bloc object |
||
407 | * |
||
408 | * \return S : The name of the bloc if success, NIL otherwise |
||
409 | **/ |
||
410 | int _GETblocName(mmachine m) |
||
411 | { |
||
412 | #ifdef _SCOL_DEBUG_ |
||
413 | MMechostr(MSKDEBUG,"_GETblocName\n"); |
||
414 | #endif |
||
415 | // Get bloc table in the stack, then transform it in system pointer |
||
416 | int blocTable = MTOP( MMget(m,0) ) ; |
||
417 | if ( blocTable == NIL ) { MMset(m,0,NIL) ; return 0 ; } |
||
418 | |||
419 | // cast this bloc in a Bloc object |
||
420 | Bloc* bloc = (Bloc*)MMfetch(m, blocTable, 0) ; |
||
421 | if( !bloc ) { MMset(m,0,NIL) ; return 0 ; } |
||
422 | |||
423 | // remove param from stack |
||
424 | MMpull(m); |
||
425 | |||
426 | // put in the stack the return of the function call |
||
427 | Mpushstrbloc(m, bloc->getName()); |
||
428 | |||
429 | #ifdef _SCOL_DEBUG_ |
||
430 | MMechostr(MSKDEBUG,"ok\n"); |
||
431 | #endif |
||
432 | |||
433 | return 0; |
||
434 | } |
||
435 | |||
436 | /*! @ingroup group1 |
||
437 | * \brief _SETblocName : Set the name of the bloc |
||
438 | * |
||
439 | * <b>Prototype:</b> fun [BlocObj S] I |
||
440 | * |
||
441 | * \param BlocObj : bloc object |
||
442 | * \param S : New name |
||
443 | * |
||
444 | * \return I : 0 if success, -1 otherwise |
||
445 | **/ |
||
446 | int _SETblocName(mmachine m) |
||
447 | { |
||
448 | #ifdef _SCOL_DEBUG_ |
||
449 | MMechostr(MSKDEBUG,"_SETblocName\n"); |
||
450 | #endif |
||
451 | // Get param |
||
452 | int name = MTOP( MMpull(m) ) ; |
||
453 | |||
454 | // Get Bloc table |
||
455 | int blocTable = MTOP( MMget(m,0) ) ; |
||
456 | if ( blocTable == NIL ) { MMset(m,0,-1) ; return 0 ; } |
||
457 | |||
458 | // Cast the content of bloc table to Bloc* |
||
459 | Bloc* bloc = (Bloc*)MMfetch(m, blocTable, 0) ; |
||
460 | |||
461 | char * sname = MMstartstr(m, name); |
||
462 | bloc->setName(sname); |
||
463 | |||
464 | MMset(m,0,0); |
||
465 | |||
466 | #ifdef _SCOL_DEBUG_ |
||
467 | MMechostr(MSKDEBUG,"ok\n"); |
||
468 | #endif |
||
469 | |||
470 | return 0; |
||
471 | } |
||
472 | </pre> |
||
473 | |||
474 | |||
475 | As explained earlier, we will add the binding of our new functions to the variables used during the registration of the package (when calling *PKhardpak*). |
||
476 | <pre> |
||
477 | //! Nb of Scol functions or types |
||
478 | #define NbTplPKG 8 |
||
479 | |||
480 | /*! |
||
481 | * Scol function names |
||
482 | **/ |
||
483 | char* TplName[NbTplPKG] = |
||
484 | { |
||
485 | "_HelloWorld", |
||
486 | "ObjBloc", |
||
487 | "_CRbloc", |
||
488 | "_DSbloc", |
||
489 | "_GETblocValue", |
||
490 | "_GETblocName", |
||
491 | "_SETblocName", |
||
492 | "_SETblocValue" |
||
493 | }; |
||
494 | |||
495 | /*! |
||
496 | * Pointers to C functions that manipulate the VM for each scol function previously defined |
||
497 | **/ |
||
498 | int (*TplFunc[NbTplPKG])(mmachine m)= |
||
499 | { |
||
500 | _HelloWorld, |
||
501 | NULL, |
||
502 | _CRbloc, |
||
503 | _DSbloc, |
||
504 | _GETblocValue, |
||
505 | _GETblocName, |
||
506 | _SETblocName, |
||
507 | _SETblocValue |
||
508 | }; |
||
509 | |||
510 | /*! |
||
511 | * Nb of arguments of each scol function |
||
512 | **/ |
||
513 | int TplNArg[NbTplPKG]= |
||
514 | { |
||
515 | 0, |
||
516 | TYPTYPE, |
||
517 | 1, |
||
518 | 1, |
||
519 | 1, |
||
520 | 1, |
||
521 | 2, |
||
522 | 2 |
||
523 | }; |
||
524 | |||
525 | /*! |
||
526 | * Prototypes of the scol functions |
||
527 | **/ |
||
528 | char* TplType[NbTplPKG]= |
||
529 | { |
||
530 | "fun [] I", // _HelloWorld |
||
531 | NULL, |
||
532 | "fun [Chn] ObjBloc", // _CRbloc |
||
533 | "fun [ObjBloc] I", // _DSbloc |
||
534 | "fun [ObjBloc] I", // _GETblocValue |
||
535 | "fun [ObjBloc] S", // _GETblocName |
||
536 | "fun [ObjBloc S] I", // _SETblocName |
||
537 | "fun [ObjBloc I] I" // _SETblocValue |
||
538 | }; |
||
539 | </pre> |
||
540 | |||
541 | |||
542 | We can now recompile the project and move the generated DLL file to the *plugins* folder of Scol Voyager. |
||
543 | |||
544 | |||
545 | h2. Use of the new data type in Scol |
||
546 | |||
547 | In this section, we will explain how to create a Scol program which will be using the *ObjBloc* data type that we have just created. |
||
548 | The first thing to do is to update the *template.pkg* file, which must still be located in the user partition of Scol Voyager, by adding the following function : |
||
549 | <pre> |
||
550 | /*! \brief Sample main function that show how to use a custom C++ type in Scol. |
||
551 | * |
||
552 | * The custom type is defined within a C++ plugin. |
||
553 | * We checks creation of a new instance of the object, setting values in, |
||
554 | * reading the values stored in, and then we manually deleting the instance. |
||
555 | * |
||
556 | * <b>Prototype:</b> fun [S I] I |
||
557 | * |
||
558 | * \param S : bloc name |
||
559 | * \param I : bloc value |
||
560 | * |
||
561 | * \return I : 0 |
||
562 | **/ |
||
563 | fun ObjBlocTest(nameValue, integerValue)= |
||
564 | let _CRbloc _channel -> blocInstance in |
||
565 | { |
||
566 | // Set ObjBloc properties values |
||
567 | _SETblocName blocInstance nameValue; |
||
568 | _SETblocValue blocInstance integerValue; |
||
569 | |||
570 | // Check if values where correctly registered and log them on the console |
||
571 | _fooS strcatn "Bloc name: "::(_GETblocName blocInstance)::"\nBloc value: "::(itoa (_GETblocValue blocInstance))::nil; |
||
572 | |||
573 | // Manually destroying blocInstance |
||
574 | _DSbloc blocInstance; |
||
575 | }; |
||
576 | 0;; |
||
577 | </pre> |
||
578 | |||
579 | |||
580 | Now, let's create a new file in our user partition, named *TestObjBloc.scol*. This program will load the *template.pkg* package that we have just updated, and run the function *ObjBlocTest* by passing to it 2 parameters. |
||
581 | It's important to notice that in Scol language, to pass an integer as a parameter in a *.scol* file, we must use its hexadecimal representation (in our case, 'ff' stands for '255'). |
||
582 | <pre> |
||
583 | _load "template.pkg" |
||
584 | ObjBlocTest "newBloc" ff |
||
585 | </pre> |
||
586 | |||
587 | |||
588 | Now, we can run the Scol program *TestObjBloc.scol*. The log file (usually located in *C:\Users\MyUser\AppData\Local\Scol Voyager\Logs*) should be close to the following lines : |
||
589 | <pre> |
||
590 | Loading C:\Users\Jeff\Documents\Scol Voyager\Partition_LocalUsr\template.pkg ... |
||
591 | typechecking |
||
592 | fun main : fun [] I |
||
593 | fun ObjBlocTest : fun [S I] I |
||
594 | Generating bytecodes for 'main'... |
||
595 | 3 bytes generated (for a total of 375 bytes) |
||
596 | Generating bytecodes for 'ObjBlocTest'... |
||
597 | 79 bytes generated (for a total of 453 bytes) |
||
598 | Loading complete |
||
599 | |||
600 | |||
601 | > exec: ObjBlocTest "newBloc" ff |
||
602 | |||
603 | _CRbloc |
||
604 | _CRbloc ...initialization successful |
||
605 | _CRbloc ...MMmalloc successful |
||
606 | _CRbloc ...object creation successful |
||
607 | ok |
||
608 | _SETblocName |
||
609 | ok |
||
610 | _SETblocValue |
||
611 | ok |
||
612 | _GETblocName |
||
613 | ok |
||
614 | _GETblocValue |
||
615 | ok |
||
616 | Bloc name: newBloc |
||
617 | Bloc value: 255 |
||
618 | _DSbloc |
||
619 | Bloc object destroyed. |
||
620 | ok |
||
621 | 1 | ModularMix | </pre> |