1% BEGIN LICENSE BLOCK 2% Version: CMPL 1.1 3% 4% The contents of this file are subject to the Cisco-style Mozilla Public 5% License Version 1.1 (the "License"); you may not use this file except 6% in compliance with the License. You may obtain a copy of the License 7% at www.eclipse-clp.org/license. 8% 9% Software distributed under the License is distributed on an "AS IS" 10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11% the License for the specific language governing rights and limitations 12% under the License. 13% 14% The Original Code is The ECLiPSe Constraint Logic Programming System. 15% The Initial Developer of the Original Code is Cisco Systems, Inc. 16% Portions created by the Initial Developer are 17% Copyright (C) 2006 Cisco Systems, Inc. All Rights Reserved. 18% 19% Contributor(s): 20% 21% END LICENSE BLOCK 22% 23% @(#)umscmacros.tex 24% 25 26%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 27% {\eclipse} Documentation 28% 29% embed.tex 30% 31%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 32\chapter{Calling {\eclipse} from C++} 33\label{chap1embed} 34%HEVEA\cutdef[1]{section} 35 36This chapter describes how {\eclipse} can be included in an external 37program as a library, how to start it, and how to 38communicate with it. Code examples are given in C++. 39For the equivalent C functions, please refer to chapter~\ref{chapsumc}. 40 41%--------------------------------------------------------------------- 42\section{To get started} 43%--------------------------------------------------------------------- 44 45This section is about the prerequisites for working with 46{\eclipse} in your development environment. The directory structure, 47the libraries and the include files are described. 48 49\subsection{Directories} 50\index{directories} 51 52The libraries and include files needed to use {\eclipse} as an 53embedded component are available under the {\eclipse} 54\index{installation directory} 55directory which was set-up during installation. If you have access 56to a stand-alone {\eclipse} it can be found using the following query 57at the {\eclipse} prompt: 58 59\begin{verbatim} 60 [eclipse 1]: get_flag(installation_directory,Dir). 61 62 Dir = "/usr/local/eclipse" 63 yes. 64 [eclipse 2] 65\end{verbatim} 66 67We will assume from here that {\eclipse} was installed in "/usr/local/eclipse". 68 69You would find the include files in "/usr/local/eclipse/include/\$ARCH" 70and the the libraries in "/usr/local/eclipse/lib/\$ARCH" where 71"\$ARCH" is a string naming the architecture of your machine. 72\index{ARCH} 73\index{architecture} 74This can be found using the following {\eclipse} query: 75 76\begin{verbatim} 77 [eclipse 2]: get_flag(hostarch,Arch). 78 79 Arch = "sun4" 80 yes. 81 [eclipse 3]: 82\end{verbatim} 83 84You will need to inform your C or C++ compiler and linker about these 85directories so that these tools can include and link the appropriate files. 86A make file "Makefile.external" can be found together with the libraries. 87\index{Makefile} 88The definitions in that makefile may have to be updated according to 89your operating system environment. 90 91A set of example C and C++ programs can be found in 92"/usr/local/eclipse/doc/examples". 93 94When delivering an application you will have to include with it the 95contents of the directory 96"/usr/local/eclipse/lib" without which {\eclipse} 97cannot work. Normally this would be copied into the directory structure 98of the delivered application. The interface can set different values 99for this directory, enabling different applications to have different 100sets of libraries. 101 102 103\subsection{Definitions} 104 105To include the definitions needed for calling the {\eclipse} library 106in a C program use: 107\index{include files} 108\begin{verbatim} 109 #include <eclipse.h> 110\end{verbatim} 111 112For C++ a more convenient calling convention can be used based on 113some classes wrapped around these C definitions. To include these use: 114 115\begin{verbatim} 116 #include <eclipseclass.h> 117\end{verbatim} 118 119 120 121\subsection{Compiling, linking and running on Unix/Linux} 122 123Assuming that the environment variable ECLIPSEDIR is set to the 124{\eclipse} installation directory and the environment variable ARCH is set to 125the architecture/operating system name, 126an application can be built as follows: 127\begin{verbatim} 128gcc -I$ECLIPSEDIR/include/$ARCH eg_c_basic.c -L$ECLIPSEDIR/lib/$ARCH -leclipse 129\end{verbatim} 130This will link your application with the shared library \verb+libeclipse.so+. 131 132At runtime, your application must be able to locate \verb+libeclipse.so+. 133This can be achieved by adding $ECLIPSEDIR/lib/$ARCH to your 134\verb+LD_LIBRARY_PATH+ environment variable. 135 136The embedded {\eclipse} finds its own support files (e.g.\ {\eclipse} libraries) 137through the \verb+ECLIPSEDIR+ environment variable. 138This must be set to the location where {\eclipse} is installed, 139e.g.\ \verb+/usr/local/eclipse+. 140Alternatively, the application can invoke \verb+ec_set_option+ to specify 141the \verb+ECLIPSEDIR+ location before initialising the embedded {\eclipse} 142with \verb+ec_init+. 143 144 145%\subsection{Static linking (Unix/Linux)} 146% 147%If your operating system only supports static linking, or if you want 148%to link statically for some reason, you have to link explicitly with 149%\verb+libeclipse.a+ and the necessary support libraries must be specified, e.g. 150%\begin{verbatim} 151%gcc -I$ECLIPSEDIR/include/$ARCH eg_c_basic.c $ECLIPSEDIR/lib/$ARCH/libeclipse.a 152% -L$ECLIPSEDIR/lib/$ARCH -lgmp -lshm -ldummies -ldl -lnsl -lsocket -lm 153%\end{verbatim} 154%The libraries \verb+gmp+, \verb+shm+ and \verb+dummies+ are {\eclipse} 155%support libraries and must be specified in that order. 156%The others are Unix libraries. 157% 158%It is recommended that you copy the makefile "Makefile.external" 159%provided in your installation directory under lib/\$ARCH and adapt it 160%for your purposes. 161%\index{Makefile} 162% If the makefile is not used, the command to compile a C++ source 163% with {\eclipse} library calls looks similar to this: 164% \begin{verbatim} 165% % g++ -I/usr/local/eclipse/include/sparc_sunos5 -c eg_cc_main.cc 166% \end{verbatim} 167% The linking of an executable with embedded {\eclipse} looks like 168% \begin{verbatim} 169% % g++ eg_cc_main.o -L/usr/local/eclipse/lib/sparc_sunos5 -leclipse 170% -lgmp -lshm -ldummies -ldl -lnsl -lsocket -lm 171% \end{verbatim} 172% The details may vary depending on what compiler and operating system 173% you use. Refer to the Makefile.external for details. 174 175 176\subsection{Compiling, linking and running on Windows} 177 178If you use GCC, you can link either directly against \verb+eclipse.dll+ 179or against \verb+eclipse.dll.a+. 180The required command line is similar to the Unix case. 181 182If you use a Microsoft compiler, make sure you have the following 183additional settings in your C/C++ compiler/development system: 184\begin{itemize} 185\item In the {\bf C/C++ Preprocessor} settings, 186specify the {\eclipse} include directory as an additional 187include directory, e.g.\ \verb+C:\Program Files\ECLiPSe 5.10\include\i386_nt+. 188\item In the {\bf Link} settings, 189specify \verb+eclipse.lib+ as an additional object/library 190module, and the location of this library, e.g.\ 191\verb+C:\Program Files\ECLiPSe 5.10\lib\i386_nt+ as an additional library path. 192\end{itemize} 193\index{eclipse.lib} 194Moreover, you need to create an \verb+eclipse.lib+ for the compiler to 195link against. This file can be created from \verb+eclipse.def+ and 196\verb+eclipse.dll+ (which are part of the {\eclipse} distribution), 197using the \verb+lib.exe+ or \verb+link.exe+ tool (which comes with the 198C/C++ development system). 199\begin{verbatim} 200 cd C:\Program Files\ECLiPSe 5.10\lib\i386_nt 201 lib.exe /def:eclipse.def 202\end{verbatim} 203Warnings about import directives can be ignored. 204If you do not have \verb+lib.exe+, try instead 205\begin{verbatim} 206 link.exe /lib /def:eclipse.def 207\end{verbatim} 208 209At runtime, your application must be able to locate \verb+eclipse.dll+, 210\index{eclipse.dll} 211i.e.\ you should either 212\begin{itemize} 213\item copy \verb+eclipse.dll+ into the folder where your application is located, or 214\item copy \verb+eclipse.dll+ into one of Windows' standard library folders, or 215\item add the path to the folder where \verb+eclipse.dll+ can be found 216 to your PATH environment variable. 217\end{itemize} 218The \verb+eclipse.dll+ finds its own support files (e.g.\ {\eclipse} libraries) 219through the \verb+ECLIPSEDIR+ registry entry under the registry key 220\verb+HKEY_LOCAL_MACHINE\SOFTWARE\IC-Parc\ECLiPSe\X.Y+ (X.Y is the version 221number). 222This must be set to the location where {\eclipse} is installed, 223e.g.\ \verb+C:/Eclipse+. 224Alternatively, the application can invoke \verb+ec_set_option+ to specify 225the \verb+ECLIPSEDIR+ location before initialising the embedded {\eclipse} 226with \verb+ec_init+. 227 228 229%--------------------------------------------------------------------- 230\section{Creating an {\eclipse} context} 231%--------------------------------------------------------------------- 232 233{\eclipse} runs as a special thread (we will call it {\eclipse} engine) within 234your application, 235maintaining its own execution state. This section is about when and 236how to initialise it. There are parameters to be applied before 237initialisation, but these are usually acceptable. These parameters are 238described in Appendix~\ref{chapecoptions}. 239 240Although it is useful to think of {\eclipse} as a thread, it is not an 241\index{thread} 242operating system thread, but is rather implemented as a set of C 243functions that maintain some state. This state is the complete 244execution state of the {\eclipse} engine, its stack of goals, its 245success and failure continuations and its global stack of all 246constructed data. 247 248At particular points during its execution {\eclipse} will yield control 249back to the C level. This is implemented by returning from a function. 250{\eclipse} can then be restarted from the exact point it left off. This 251is implemented by a function call. 252 253\subsection{Initialisation} 254 255You initialise {\eclipse} by calling the parameterless function 256\index{initialisation} 257\begin{verbatim} 258 int ec_init(); 259\end{verbatim} 260 261A process should do this just once. \verb.ec_init. returns 0 on success or 262-1 if an error occurred. It is possible to influence the initialisation of 263{\eclipse} by setting initialisation options as described in 264Appendix~\ref{chapecoptions}. 265 266None of the functions of the interface work before this initialisation. In 267particular in C++, if you use static variables which are 268constructed by calling {\eclipse} functions you must arrange for the 269initialisation to occur before the constructors are called. 270 271 272%--------------------------------------------------------------------- 273\section{Control flow} 274%--------------------------------------------------------------------- 275 276{\eclipse} and a C or C++ main program are like threads running in a 277single process. Each maintains its state and methods for exchanging 278\index{thread} 279\index{state} 280data and yielding control to the other thread. 281 282The main method of sending data from C++ to {\eclipse} is by posting 283\index{posting goals} 284goals for it to solve. All posted goals are solved in conjunction 285with each other, and with any previously posted goals that have 286succeeded. 287 288Data is passed back by binding logical variables within the goals. 289\index{logical variable} 290 291\index{resume} 292Control is explicit in C++. After posting some goals, the C++ program 293calls the \verb.EC_resume(). function and these goals are all 294solved. A return code says whether they were successfully solved 295or whether a failure occurred. 296 297 298In {\eclipse} control is normally implicit. Control returns to C++ when all 299goals have been solved. 300 301\begin{verbatim} 302 #include "eclipseclass.h" 303 304 main() 305 { 306 ec_init(); 307 308 /* writeln("hello world"), */ 309 post_goal(term(EC_functor("writeln",1),"hello world")); 310 EC_resume(); 311 ec_cleanup(0); 312 } 313\end{verbatim} 314The above is an example program that posts a goal and executes it. 315 316\subsection{Control flow and search} 317 318Using this model of communication it is possible to construct programs where 319execution of C++ code and search within the {\eclipse} are interleaved. 320 321\index{posting goals} 322\index{failure} 323\index{backtracking} 324If you post a number of goals (of which some are non-deterministic) and 325resume the {\eclipse} execution and the goals succeed, then control returns 326to the C++ level. By posting a goal that fails, the {\eclipse} execution 327will fail back into the previous set of goals and these will succeed with 328a different solution. 329 330\begin{verbatim} 331 #include "eclipseclass.h" 332 333 main() 334 { 335 ec_init(); 336 EC_ref Pred; 337 338 post_goal(term(EC_functor("current_built_in",1),Pred)); 339 while (EC_succeed == EC_resume()) 340 { 341 post_goal(term(EC_functor("writeln",1),Pred)); 342 post_goal(EC_atom("fail")); 343 } 344 ec_cleanup(0); 345 } 346\end{verbatim} 347The above example prints all the built ins available in {\eclipse}. 348When \verb.EC_resume(). returns \verb.EC_succeed. there is a solution 349to a set of posted goals, and we print out the value of \verb.Pred.. 350otherwise \verb.EC_resume(). returns \verb.EC_fail. to indicate 351that no more solutions to any set of posted goals is available. 352 353\index{cut} 354It is possible also to cut such search. So for example one could modify 355the example above to only print the 10th answer. Initially one simply 356fails, but at the tenth solution one cuts further choices. Then 357one prints the value of 'Pred'. 358 359\begin{verbatim} 360 #include "eclipseclass.h" 361 362 main() 363 { 364 ec_init(); 365 EC_ref Pred,Choice; 366 int i = 0; 367 368 post_goal(term(EC_functor("current_built_in",1),Pred)); 369 while (EC_succeed == EC_resume(Choice)) 370 { 371 if (i++ == 10) 372 { 373 Choice.cut_to(); 374 break; 375 } 376 post_goal(term(EC_atom("fail"))); 377 } 378 post_goal(term(EC_functor("writeln",1),Pred)); 379 EC_resume(): 380 ec_cleanup(0); 381 } 382\end{verbatim} 383 384\index{choicepoint} 385When \verb.EC_resume(). is called with an \verb.EC_ref. argument, this 386is for data returned by the \verb.EC_resume(). If the return code is 387\verb.EC_succeed. The \verb.EC_ref. is set to a choicepoint identifier 388which can be used for cutting further choices at that point. 389 390\subsection{Asynchronous events} 391 392\index{events} 393\index{posting events} 394The posting of goals and building of any {\eclipse} terms in general 395cannot be done asynchronously to the {\eclipse} execution. It has to 396be done after the \verb.EC_resume(). function has returned. 397 398\index{asynchronous} 399Sometimes it may be necessary to signal some asynchronous event to 400{\eclipse}, for example to implement a time-out. To do this one 401posts a named event to {\eclipse}. At the next synchronous point 402within the eclipse execution, the handler for that event is 403invoked. 404\begin{verbatim} 405 /* C++ code, possibly within a signal handler */ 406 post_event(EC_atom("timeout")); 407 408 /* ECLiPSe code */ 409 handle_timeout(timeout) :- 410 <appropriate action> 411 412 :- set_event_handler(timeout, handle_timeout/1). 413\end{verbatim} 414 415 416\subsection{The yield-resume model} 417 418\index{passing data} 419\index{yield} 420\index{resume} 421Although implicitly yielding control when a set of goals succeeds 422or fails is often enough, it is possible to explicitly yield 423control to the C++ level. This is done with the 424\bipref{yield/2}{../bips/kernel/externals/yield-2.html} 425predicate. This yields control to the calling C++ program. 426The arguments are used for passing data to C++ and from C++. 427 428When \bipref{yield/2}{../bips/kernel/externals/yield-2.html} is called within {\eclipse} code, the \verb.EC_resume(). 429function returns the value \verb.EC_yield. so one can recognise this case. 430The data passed out via the first argument of \bipref{yield/2}{../bips/kernel/externals/yield-2.html} 431can be accessed from C++ via the \verb.EC_ref. argument to \verb.EC_resume().. 432The data received in the second argument of \bipref{yield/2}{../bips/kernel/externals/yield-2.html} is either 433the list of posted goals, or an \verb.EC_word. passed as an input 434argument to \verb.EC_resume().. 435 436\begin{verbatim} 437 yield(out(1,2),InData), 438\end{verbatim} 439 440In this example the compound term \verb.out(1,2). is passed to C++. 441If we had previously called: 442\begin{verbatim} 443 EC_ref FromEclipse; 444 result = EC_resume(FromEclipse); 445\end{verbatim} 446then \verb.result. would be \verb.EC_yield. and \verb.FromEclipse. would 447refer to \verb.out(1,2).. If then we resumed execution with: 448\begin{verbatim} 449 result = EC_resume(EC_atom("ok"),FromEclipse); 450\end{verbatim} 451then the variable \verb.InData. on the {\eclipse} side 452would be set to the atom 'ok'. 453 454 455\subsection{Summary of EC_resume() arguments} 456 457\index{passing data} 458\verb.EC_resume(). can be called with two optional arguments. An 459input argument that is an \verb.EC_word. and an output that is an 460\verb.EC_ref.. 461 462If the input argument is omitted, input is taken as the list of posted 463goals. Otherwise the input to {\eclipse} is exactly that argument. 464 465If the output argument is present, its content depends on the value 466returned by \verb.EC_resume().. If it returns \verb.EC_succeed. it is 467\index{choicepoint} 468the choicepoint identifier. If it returns \verb.EC_yield. It is the 469first argument to the \bipref{yield/2}{../bips/kernel/externals/yield-2.html} goal. If it returns \verb.EC_fail. 470it is not modified. 471%HEVEA\cutend 472 473 474%--------------------------------------------------------------------- 475\chapter{Managing Data and Memory in Mixed-Language Applications} 476\label{chapmixed} 477%HEVEA\cutdef[1]{section} 478%--------------------------------------------------------------------- 479 480{\eclipse} is a software engine for constraint propagation and search tasks. 481As such, it represents its data in a form that is different 482from how it would be represented in a traditional C/C++ program. 483\index{search} 484\index{garbage collection} 485\index{memory management} 486In particular, 487the {\eclipse} data representation supports automatic memory management 488and garbage collection, modifications that can be undone in a search context, 489referential transparency and dynamic typing. 490 491In a mixed-language application, there are two basic ways of communicating 492information between the components coded in the different languages: 493\index{passing data} 494\begin{description} 495\item[Conversion:] When data is needed for processing in another language, 496 it can be converted to the corresponding representation. 497 This technique is appropriate for simple data types (integers, strings), 498 but can have a lot of overhead for complex structures. 499\item[Sharing:] The bulk of the data is left in its original representation, 500 referred to by a handle, and interface functions (or methods) provide 501 access to its components when required. 502\end{description} 503Both techniques are supported by the {\eclipse}/C and {\eclipse}/C++ interface. 504 505 506%-------------------------------- 507\section{Constructing {\eclipse} data} 508%-------------------------------- 509\subsection{{\eclipse} atoms and functors} 510 511\index{passing data} 512\index{atom} 513\index{functor} 514\begin{verbatim} 515 /* ECLiPSe code */ 516 S = book("Gulliver's Tales","Swift",hardback,fiction), 517\end{verbatim} 518 519In the above structure 'hardback' and 'fiction' are atoms. 'book' 520is the functor of that structure, and it has an arity (number 521of arguments) of 4. 522 523Each functor and atom is entered into a dictionary, and is always 524referred to by its dictionary entry. Two classes, \verb.EC_atom. 525and \verb.EC_functor. are used to access such dictionary entries. 526 527The 'Name' method applies to both, to get their string form. 528The 'Arity' method can be used to find out how many arguments 529a functor has. 530 531\begin{verbatim} 532 /* C++ code */ 533 EC_functor book("book",4); 534 EC_atom hardback("hardback"); 535 536 if (book.Arity()) == 4) .. /* evaluates to true */ 537 if (book == hardback) .. /* evaluates to false */ 538 s = hardback.Name(); /* like s = "hardback"; */ 539\end{verbatim} 540 541 542\subsection{Building {\eclipse} terms} 543 544\index{pword} 545\index{EC_word} 546\index{term} 547The \verb.pword. C data type is used to store {\eclipse} terms. In C++ the 548\verb.EC_word. data type is used. This is used for any C type as well 549as for {\eclipse} structures and lists. The size remains fixed in all 550cases, since large terms are constructed on the {\eclipse} global stack. 551 552\index{garbage collection} 553The consequences of this are that terms will be garbage collected 554or moved so terms do not survive the execution of {\eclipse}. In 555particular, one cannot build such terms asynchronously while 556{\eclipse} is running, for example this precludes building terms from 557within a signal handler unless it can make sure that {\eclipse} has 558yielded when it is running. 559 560\subsection{Building atomic {\eclipse} terms} 561It is possible to simply cast from a number of simple C++ types to 562build an \verb.EC_word. In addition, functions exist for creating 563\index{logical variable} 564new variables, and for the nil which terminates {\eclipse} lists. 565In C++ you can just cast. 566\begin{verbatim} 567 /* making simple terms in C++ */ 568 EC_word w; 569 EC_atom hardback("hardback"); 570 w = (EC_word) "Swift"; 571 w = (EC_word) hardback; 572 w = (EC_word) 1.002e-7; 573 w = (EC_word) 12345; 574 w = (EC_word) nil(); 575 w = (EC_word) newvar(); 576 577 /* ECLiPSe equivalent code */ 578 P1 = "Swift", 579 P2 = hardback, 580 P3 = 1.002e-7, 581 P4 = 12345, 582 P5 = [], 583 P6 = _, 584\end{verbatim} 585 586\subsection{Building {\eclipse} lists} 587\index{list} 588The \verb.list(head,tail). function builds a list out of two terms. Well 589formed lists have lists as their tail term and a nil ("[]") at the end, or a 590variable at the end for difference lists. 591 592\begin{verbatim} 593 /* making the list [1, "b", 3.0] in C++ */ 594 EC_word w = list(1, list("b", list(3.0, nil()))); 595\end{verbatim} 596 597The following example shows how you can write functions to build 598variable length lists. 599 600\begin{verbatim} 601/* function to build a list [n,n+1,n+2,.....,m-1,m] */ 602EC_word fromto(int n, int m) 603{ 604 EC_word tail = nil(); 605 for(int i = m ; i >= n ; i--) 606 tail = list(i,tail); 607 return tail; 608} 609\end{verbatim} 610 611The list is constructed starting from the end, so at all points during its 612construction you have a valid term. The interface is designed to 613make it hard to construct terms with uninitialised sub-terms, which is 614what you would need if you were to construct the list starting with 615the first elements. 616 617\subsection{Building {\eclipse} structures} 618\index{term} 619\index{structure} 620\index{compound term} 621The \verb%term(functor,args..)% function is used to build {\eclipse} 622structures. A number of different functions each with a different 623number of arguments is defined so as not to disable C++ casting 624which would be the case if we defined a function with variable 625arguments. 626 627\begin{verbatim} 628 /* making s(1,2,3) in C++ */ 629 EC_functor s_3("s",3); 630 EC_word w = term(s_3,1,2,3); 631\end{verbatim} 632 633The above interface is convenient for terms with small fixed arities, 634for much larger terms an array based interface is provided. 635 636\begin{verbatim} 637 /* making s(1,2,..,n-1,n) */ 638 EC_word args[n]; 639 for(int i=0 ; i<n ; i++) 640 args[i] = i+1; 641 EC_word w = term(EC_functor("s",n),args); 642\end{verbatim} 643 644 645%-------------------------------- 646\section{Converting {\eclipse} data to C data} 647%-------------------------------- 648 649\index{type testing} 650There are several aspects to examining the contents of a term. These 651include decomposing compound terms such as lists and structures, 652converting simple terms to C data types and testing the types of terms. 653 654The functions for decomposing and converting check that the type 655is appropriate. If it is they return \verb.EC_succeed. if not 656they return a negative error code. 657 658\subsection{Converting simple {\eclipse} terms to C data types} 659 660To convert from an {\eclipse} term to a C type you first have to 661declare a variable with that type. For fixed size data types 662(you can convert to \verb.double., \verb.long. and \verb.dident. 663fixed size data types) you are responsible for allocating the 664memory. For strings you declare a \verb.char*. variable and 665on conversion it will point to the internal {\eclipse} string. 666\index{string} 667 668In the following example we see how one can try to convert to 669different types. Of course normally you will know what type 670you are expecting so only one of these functions need be called. 671\begin{verbatim} 672 EC_word term; 673 double r; 674 long i; 675 EC_atom did; 676 char *s; 677 if (EC_succeed == term.is_double(&d)) 678 cout << d << "\n"; 679 else if (EC_succeed == term.is_long(&i)) 680 cout << i << "\n"; 681 else if (EC_succeed == term.is_atom(&did)) 682 cout << did.Name() << "\n"; 683 else if (EC_succeed == term.is_string(&s)) 684 cout << s << "\n"; 685 else 686 cout << "not a simple type\n"; 687\end{verbatim} 688 689The term is converted by the function which returns \verb.EC_success.. 690The functions that fail to convert will return a negative error number. 691 692\index{string} 693\index{garbage collection} 694Care has to be taken with strings, these pointers point to the internal 695{\eclipse} string which may move or be garbage collected during an {\eclipse} 696execution. As a result if a string is to be kept permanently one should 697copy it first. 698 699 700\subsection{Decomposing {\eclipse} terms} 701 702The function \verb.ec_get_arg(index,term,&subterm). is used to get 703the index'th subterm of a structure. The index varies from 1 to 704arity of \verb.term.. A list can also be decomposed this way, where 705the head is at index 1 and the tail at index 2. 706\index{list} 707\index{structure} 708 709Below we see how we would write a function to find the nth element of 710a list. 711\begin{verbatim} 712 int nth(const int n,const EC_word list, EC_word& el) 713 { 714 EC_word tail = list; 715 for (int i=1, i<n, i++) 716 if (EC_fail == tail.arg(2,tail)) 717 return EC_fail; 718 return tail.arg(1,el); 719 } 720\end{verbatim} 721The above function actually is not limited to lists but could work 722on any nested structure. 723 724 725%-------------------------------- 726\section{Referring to {\eclipse} terms} 727%-------------------------------- 728 729The terms constructed so far (as EC-words) have been volatile, that is they 730do not survive an {\eclipse} execution (due to eg.\ garbage collection), 731\index{garbage collection} 732It is possible to create safe terms 733that have been registered with the {\eclipse} engine and which do 734survive execution. The \verb.EC_ref. and \verb.EC_refs. classes 735are provided for this purpose. \verb.EC_refs. are vectors of 736safe terms. 737 738When you declare an \verb.EC_ref. it will contain free variables. 739\begin{verbatim} 740EC_ref X; /* declare one free variable */ 741EC_refs Tasks(10); /* declare 10 free variables */ 742\end{verbatim} 743 744 745\index{logical variables} 746\verb.EC_ref.s work like logical variables. When {\eclipse} fails during search 747they are reset to old values. They are always guaranteed to refer to 748something i.e.\ they never contain dangling references. 749If {\eclipse} backtracks to a point in the execution 750older than the point at which the references were created, they 751return to being free variables, or take on their initial values. 752 753\index{references} 754It is possible to declare references, giving them an initialiser 755but this must be an atomic type that fits into a single word. That 756restricts you to atoms, integers and nil. 757 758You can freely assign between an \verb.EC_ref. and a \verb.EC_word.. 759 760One point to take care of is that assigning such a variable 761is not like unification since assignment cannot fail. It 762just overwrites the old value. Assignment is very similar 763to the \bipref{setarg/3}{../bips/kernel/termmanip/setarg-3.html} built-in in the {\eclipse} language. 764 765 766%--------------------------------------------------------------------- 767\section{Passing generic C or C++ data to {\eclipse}} 768%--------------------------------------------------------------------- 769 770\index{references} 771It is possible to include any C or C++ data in an {\eclipse} term. To do this 772it is wrapped into a handle to tell {\eclipse} that this is external data. 773You also have to supply a method table, which is a set of functions 774that are called when {\eclipse} wants to make common operations that it 775assumes can be done on any data (eg.\ comparing, printing). 776 777 778\subsection{Wrapping and unwrapping external data in an {\eclipse} term} 779 780To create an {\eclipse} wrapper for a C/C++ object, 781the function \verb.handle(). is used. It takes a pointer to any C or C++ 782data, and a pointer to a suitable method table (\verb.t_ext_type. structure) 783and creates an {\eclipse} handle term which refers to them. 784Method tables for the common case of arrays of char, long or double 785\index{array} 786are predefined. For example a handle for a double array is made like this 787\begin{verbatim} 788 double my_array[5] = {1.1, 2.2, 3.3, 4.4, 5.5}; 789 EC_word w = handle(&ec_xt_double_arr, my_array); 790\end{verbatim} 791where \verb.ec_xt_double_arr. is a predefined method table for arrays of doubles. 792To convert back from an {\eclipse} term \verb.is_handle(). is used. 793The method table passed in indicates the sort of data you expect to get. 794If the {\eclipse} handle contains the wrong sort, the function returns 795TYPE_ERROR: 796\begin{verbatim} 797 if ((EC_succeed == w.is_handle(&ec_xt_double_arr, &obj)) 798 obj->my_method(); 799 else 800 cerr << "unexpected type\n"; 801\end{verbatim} 802 803The creation of the handle copies the address of the array, rather than the 804array itself, so the handle must be used within the scope of the array. 805 806\subsection{The method table} 807\index{method table} 808Apart from the predefined method tables ec_xt_double_arr, 809ec_xt_long_arr and ec_xt_char_arr, new ones can easily be defined. 810The address of the table is used as a type identifier, so when you 811get an external object back from {\eclipse} you can check its type 812to determine the kinds of operations you can do on it. 813You can choose not to implement one or more of these functions, by 814leaving a null pointer (\verb.(void*)0.) in its field. 815 816\begin{verbatim} 817 typedef void *t_ext_ptr; 818 819 typedef struct { 820 void (*free) (t_ext_ptr obj); 821 t_ext_ptr (*copy) (t_ext_ptr obj); 822 void (*mark_dids) (t_ext_ptr obj); 823 int (*string_size)(t_ext_ptr obj, int quoted); 824 int (*to_string) (t_ext_ptr obj, char *buf, int quoted); 825 int (*equal) (t_ext_ptr obj1, t_ext_ptr obj2); 826 t_ext_ptr (*remote_copy)(t_ext_ptr obj); 827 EC_word (*get) (t_ext_ptr obj, int idx); 828 int (*set) (t_ext_ptr obj, int idx, EC_word data); 829 } t_ext_type; 830\end{verbatim} 831 832\begin{description} 833\item[void free(t_ext_ptr obj)] 834\index{references} 835This is called by {\eclipse} if it loses a reference to the external 836data. This could happen if the {\eclipse} execution were to fail 837to a point before the external object was created, or if a 838permanent copy was explicitly removed with built-ins like 839\bipref{setval/2}{../bips/kernel/storage/setval-2.html}, 840\bipref{erase/2}{../bips/kernel/record/erase-2.html} 841or \bipref{bag_dissolve/2}{../bips/kernel/storage/bag_dissolve-2.html}. 842Note that an invocation of this function only means that {\em one} 843reference has been deleted (while the copy function indicates that 844a reference is added). 845 846\item[t_ext_ptr copy(t_ext_ptr obj)] 847This is called by {\eclipse} when it wants to make a copy of an object. 848This happens when calling {\eclipse} built-ins like \bipref{setval/2}{../bips/kernel/storage/setval-2.html} or 849\bipref{recordz/2}{../bips/kernel/record/recordz-2.html} which make permanent copies of data. The return value is 850the copy. 851If no copy-method is specified, these operations will not be possible 852with terms that contain an object of this type. 853A possible implementation is to return a pointer to the original and 854e.g.\ increment a reference counter (and decrement the counter in 855the free-method correspondingly). 856 857\item[void mark_dids( t_ext_ptr obj)] 858This is called during dictionary garbage collection. If an external 859object contains references to the dictionary (\verb.dident.) then 860it needs to mark these as referenced. 861 862\item[int string_size(t_ext_ptr obj, int quoted)] 863\item[int to_string(t_ext_ptr obj,char *buf, int quoted)] 864When {\eclipse} wants to print an external object it calls \verb.string_size(). 865to get an estimate of how large the string would be that represents it. 866This is used by {\eclipse} to allocate a buffer. The string representation must 867be guaranteed to fit in the buffer. 868 869Finally the \verb.to_string(). function is called. This should write the 870string representation of the object into the buffer, and return the actual 871size of that string. 872 873\item[int equal(t_ext_ptr obj1, t_ext_ptr obj2)] 874This is called when two external objects are unified or compared. 875Prolog views the external object as a ground, atomic element. 876It should return non-zero if the objects are considered equal. 877 878\item[t_ext_ptr remote_copy(t_ext_ptr obj)] 879This is called by parallel {\eclipse} when it needs to make a copy of an 880object in another worker. If the object is in shared memory, this method 881can be the same as the copy method. 882 883\item[EC_Word get(t_ext_ptr obj, int idx)] 884Returns the value of a field of the C/C++ object. 885This methods gets invoked when the {\eclipse} predicate \bipref{xget/3}{../bips/kernel/externals/xget-3.html} is called. 886The get/set method pair determines the mapping of index values to fields. 887 888\item[int set(t_ext_ptr obj, int idx, EC_word data)] 889Set the value of a field of the C/C++ object. 890This methods gets invoked when the {\eclipse} predicate \bipref{xset/3}{../bips/kernel/externals/xset-3.html} is called. 891The get/set method pair determines the mapping of index values to fields. 892\end{description} 893 894Example of the simplest possible user-defined method table: 895\begin{verbatim} 896 /* the initializer is actually not needed, NULLs are the default */ 897 t_ext_type my_type = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; 898 my_struct data_in; 899 ... 900 // creating a handle for data_in 901 EC_word w = handle(&my_type, &data_in); 902 ... 903 // checking a handle and extracting the data pointer 904 my_struct *data_out; 905 if ((EC_succeed == w.is_handle(&my_type, &data_out)) 906 data_out->my_method(); 907 else 908 cerr << "unexpected type\n"; 909\end{verbatim} 910 911%HEVEA\cutend 912 913 914