source: trunk/src/cee/rappture_interface.c @ 47

Last change on this file since 47 was 47, checked in by dkearney, 16 years ago

fixed python interface memory problem with py_decref() where i was decreffing a python object before i was finished using it.
this is a fix for shaikh's dgfet code not printing large amounts of data to the run.xml file.

File size: 26.3 KB
Line 
1#include "rappture_interface.h"
2
3/**********************************************************************/
4// FUNCTION: PyObject* importRappture()
5/// fxn to mimic/implement the python call "import Rappture"
6/**
7 * Clients use this function to import the Rappture module into
8 *          the Python Interpretor.
9 *
10 * Notes: It is the client's responsibility to increment and
11 *          decrement the reference count of the returned object
12 *          as needed.
13 *
14 * Returns pointer (PyObject*) to the Rappture.library class
15 *          if successful, or NULL if something goes wrong.
16 */
17
18
19PyObject* importRappture()
20{
21   
22    // it is the callers responsibility to Py_DECREF the returned object
23    // if it exists.
24
25    PyObject* pName     = NULL;
26    PyObject* pModule   = NULL;
27    PyObject* mClass    = NULL;
28    PyObject* retVal    = NULL;    /* return object */
29
30    // create a string object holding the name of the module
31    pName = PyString_FromString("Rappture");
32
33    if (pName) {
34        pModule = PyImport_Import(pName);
35        if (pModule) {
36            /* fetch module.class */
37            mClass = PyObject_GetAttrString(pModule, "library");
38            Py_DECREF(pModule);
39
40            if (mClass) {
41                // try to instantiate the class
42                if (PyCallable_Check(mClass)) {
43
44                    retVal = mClass;
45                   
46                }
47                else {
48                    // mClass not callable
49                    // something went wrong
50                    // python will probably raise error
51                }
52
53                // not sure if we need to increase and decrease
54                // increase because we are returning a ref to the object
55                // decrease because this function no longer needs the ref.
56                //
57                // the decrease is left as an exercise to the calling fxn.
58                //
59                // Py_DECREF(mClass);
60            }
61
62            // Py_DECREF(pModule);
63        }
64        else {
65            // pModule was not created
66        }
67
68        Py_DECREF(pName);
69    }
70    else {
71        // pName was not able to be created as a PyObject string
72    }       
73
74    return retVal;
75
76
77
78/**********************************************************************/
79// FUNCTION: PyObject* createRapptureObj(PyObject* rpObj, const char* path)
80/// fxn to mimic/implement the python call "lib = Rappture.library(".")"
81/// fxn instatiates a Rappture Object and returns it to the caller.
82/**
83 * Clients use this function to create a Rappture object which can
84 *          access the Rappture member functions.
85 *
86 * Notes: It is the client's responsibility to increment and
87 *          decrement the reference count of the returned object
88 *          as needed.
89 *       
90 *        Neither of the two arguments (rpObj,path) are optional.
91 *          if either value is NULL, NULL will be returned.
92 *
93 * Returns pointer (PyObject*) to an instantiated Rappture object
94 *          if successful, or NULL if something goes wrong.
95 */
96
97PyObject* createRapptureObj (PyObject* rpObj, const char* path)
98{
99    PyObject* args      = NULL;      /* args tuple */
100    PyObject* stringarg = NULL;      /* string of arguments */
101    PyObject* lib       = NULL;      /* results from fxn call */
102    PyObject* retVal    = NULL;      /* fxn return value */
103
104    long int fileLength = 0;
105    char* fileContents = NULL;
106    FILE* fp = NULL;
107
108
109    if (rpObj) {
110        if (path) {
111
112            fp = fopen(path,"rb");
113            if (fp) {
114                fseek(fp, 0, SEEK_END);
115                fileLength = ftell(fp);
116                rewind(fp);
117            }
118            fileContents = (char*) calloc(fileLength,sizeof(char));
119
120            if (fp && fileContents) {
121                fread((void*)fileContents,sizeof(char),fileLength,fp);
122                fclose(fp);
123                fp = NULL;
124
125                // setup our arguments in a Python tuple
126                args = PyTuple_New(1);
127                stringarg = PyString_FromString(fileContents);
128               
129                // clean up used memory
130                free (fileContents);
131                fileContents = NULL;
132               
133                PyTuple_SetItem(args, 0, stringarg);
134                       
135                // call the class ... lib = Rappture.library("...")
136                lib = PyObject_CallObject(rpObj, args);
137               
138                // following line could cause a segfault if used in place of above
139                // maybe path could == NULL or bad memory
140                // lib = PyObject_CallFunction(rpObj,"(s)", path);
141
142                if (lib) {
143                    // return the Rappture instantiation.
144                    retVal = lib;
145                }
146                else {
147                    // lib was not successfully created
148                }
149
150                Py_DECREF(stringarg);
151                Py_DECREF(args);
152            }
153            else {
154                // fp or fileContents were NULL;
155            }
156        }
157        else {
158            // path was null
159        }
160    }
161    else {
162        // rpObj was null
163    }
164
165    return retVal;
166
167}
168
169/**********************************************************************/
170// FUNCTION: void* rpElement(PyObject* lib, const char* path, const char* flavor)
171/// fxn to mimic/implement the python call "element = lib.element("..")"
172/// fxn calls the element() member function of the Rappture.library
173///     class and returns the text to the caller
174/**
175 * Clients use this function to call the element() member function of the
176 *          Rappture.library class and get the text of the Rappture
177 *          object lib.
178 *
179 * Notes:   If (flavor == "object") || (flavor == NULL),
180 *          1) it is the client's responsibility to increment and
181 *             decrement the reference count of the returned object
182 *             as needed.
183 *          2) the return object will need to be cast as a PyObject*
184 *             to use it.
185 *
186 *          If (flavor == type) || (flavor == id) || (flavor == component),
187 *          1) the return object will need to be cast as a char*
188 *             to use it.
189 *       
190 *        The Arguments lib and pathare not optional.
191 *          If either value is NULL, NULL will be returned.
192 *
193 * Returns pointer (char*) to the c style string representing the
194 *          xml text of the Rappture object if successful, or
195 *          NULL if something goes wrong.
196 */
197
198void* rpElement(PyObject* lib, const char* path, const char* flavor)
199{
200    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
201    PyObject* rslt      = NULL;      /* results from fxn call */
202    void* retVal        = NULL;      /* fxn return value */
203
204    if (lib && path) {
205       
206        // retrieve the lib.element() function
207        mbr_fxn = PyObject_GetAttrString(lib, "element");
208
209        if (mbr_fxn) {
210
211            if (PyCallable_Check(mbr_fxn)) {
212               
213                // call the lib.element() function with arguments
214                if (flavor) {
215                    rslt = PyObject_CallFunction(mbr_fxn,"(ss)", path, flavor);
216                }
217                else {
218                    rslt = PyObject_CallFunction(mbr_fxn,"(s)", path);
219                }
220
221                if (rslt) {
222
223                    if (flavor == NULL) {
224                        // return a PyObject*
225                        retVal = (void*) rslt;
226                    }
227                    else if((*flavor == 'o')&&(strncmp(flavor,"object", 6)==0)){
228                        // return a PyObject*
229                        retVal = (void*) rslt;
230                    }
231                    else if (
232                      ((*flavor == 't')&&(strncmp(flavor,"type", 4) == 0))
233                    ||((*flavor == 'i')&&(strncmp(flavor,"id", 2) == 0))
234                    ||((*flavor == 'c')&&(strncmp(flavor,"component", 9) == 0)))
235                    {
236                        // return a char*
237                        // convert the result to c style strings
238                        retVal = (void*) PyString_AsString(rslt);
239                        Py_DECREF(rslt);
240                    }
241                    else {
242                        // unrecognized format
243                    }
244                   
245                    // Py_DECREF(rslt);
246
247                } // rslt was null
248               
249            } // mbr_fxn was not callable
250           
251            Py_DECREF(mbr_fxn);
252        } // mbr_fxn was null
253    }
254    else {
255        // lib or path was set to NULL
256    }
257
258    return retVal;
259}
260
261
262/**********************************************************************/
263// FUNCTION: void** rpChildren(PyObject* lib, const char* path, const char* flavor)
264/// fxn to mimic/implement the python call "xmlText = lib.children("..")"
265/// fxn calls the element() member function of the Rappture.library
266///     class and returns the text to the caller
267/**
268 * Clients use this function to call the xml() member function of the
269 *          Rappture.library class and get the text of the Rappture
270 *          object lib.
271 *
272 * Notes:   If (flavor == "object") || (flavor == NULL),
273 *          1) it is the client's responsibility to increment and
274 *             decrement the reference count of the returned object
275 *             as needed.
276 *          2) the return object will need to be cast as a PyObject*
277 *             to use it.
278 *
279 *          If (flavor == "type")||(flavor == "id")||(flavor == "component"),
280 *          1) the return object will need to be case as a char*
281 *             to use it.
282 *       
283 *        The Arguments lib and pathare not optional.
284 *          If either value is NULL, NULL will be returned.
285 *
286 * Returns pointer (char*) to the c style string representing the
287 *          xml text of the Rappture object if successful, or
288 *          NULL if something goes wrong.
289 */
290
291void** rpChildren(PyObject* lib, const char* path, const char* flavor)
292{
293    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
294    PyObject* rslt      = NULL;      /* results from fxn call */
295    PyObject* list_item = NULL;      /* item from list of returned children */
296//    void* retVal        = NULL;      /* fxn return value */
297    int list_size       = 0;
298    int index           = 0;
299    char** rslt_arr_c   = NULL;
300    void** rslt_arr  = NULL;
301
302    if (lib && path) {
303       
304        // retrieve the lib.children() function
305        mbr_fxn = PyObject_GetAttrString(lib, "children");
306
307        if (mbr_fxn) {
308
309            if (PyCallable_Check(mbr_fxn)) {
310               
311                // call the lib.element() function with arguments
312                if (flavor) {
313                    rslt = PyObject_CallFunction(mbr_fxn,"(ss)", path, flavor);
314                }
315                else {
316                    rslt = PyObject_CallFunction(mbr_fxn,"(s)", path);
317                }
318
319                if (rslt) {
320
321                    if (flavor == NULL) {
322                        // return a PyObject*
323                        // retVal = (void*) rslt;
324                        //
325                        // the PyObject* points to a list, so we need to
326                        // convert this to an array of char*'s
327
328                        list_size = PyList_Size(rslt);
329                        rslt_arr = (void**) calloc(list_size+1,sizeof(void*));
330                        if (rslt_arr) {
331                            while (index < list_size) {
332                                // list_item is a borrowed reference
333                                list_item = PyList_GetItem(rslt,index);
334                                rslt_arr[index] = (void*) (list_item);
335                                index++;
336                            }
337                            // *(rslt_arr[index]) = (void*)NULL;
338                        }
339                    }
340                    else if((*flavor == 'o')&&(strncmp(flavor,"object", 6)==0)){
341                        // return a PyObject*
342                        // retVal = (void*) rslt;
343                        //
344                        // the PyObject* points to a list, so we need to
345                        // convert this to an array of char*'s
346
347                        list_size = PyList_Size(rslt);
348                        rslt_arr = (void**) calloc(list_size+1,sizeof(void*));
349                        if (rslt_arr) {
350                            while (index < list_size) {
351                                // list_item is a borrowed reference
352                                list_item = PyList_GetItem(rslt,index);
353                                rslt_arr[index] = (void*) (list_item);
354                                index++;
355                            }
356                            // *(rslt_arr[index]) = NULL;
357                        }
358                    }
359                    else if (
360                      ((*flavor == 't')&&(strncmp(flavor,"type", 4) == 0))
361                    ||((*flavor == 'i')&&(strncmp(flavor,"id", 2) == 0))
362                    ||((*flavor == 'c')&&(strncmp(flavor,"component", 9) == 0)))
363                    {
364                        // the PyObject* points to a list, so we need to
365                        // convert this to an array of char*'s
366
367                        list_size = PyList_Size(rslt);
368                        rslt_arr_c = (char**) calloc(list_size+1,sizeof(char*));
369                        if (rslt_arr_c) {
370                            while (index < list_size) {
371                                // list_item is a borrowed reference
372                                list_item = PyList_GetItem(rslt,index);
373                                // we cannot deallocate the results of
374                                // PyString_AsString()
375                                rslt_arr_c[index] = PyString_AsString(list_item);
376                                index++;
377                               
378                            }
379                            // *(rslt_arr[index]) = NULL;
380                            rslt_arr = (void**) rslt_arr_c;
381                        }
382                        // return a char*
383                        // convert the result to c style strings
384                        // retVal = (void*) PyString_AsString(rslt);
385                        Py_DECREF(rslt);
386                    }
387                    else {
388                        // unrecognized format
389                    }
390                   
391                    // Py_DECREF(rslt);
392
393                } // rslt was null
394               
395            } // mbr_fxn was not callable
396           
397            Py_DECREF(mbr_fxn);
398        } // mbr_fxn was null
399    }
400    else {
401        // lib or path was set to NULL
402    }
403
404    // return retVal;
405    return (void**) rslt_arr;
406}
407
408/**********************************************************************/
409// FUNCTION: PyObject* rpChildren_f(PyObject* lib, const char* path, const char* flavor)
410/// fxn to mimic/implement the python call "xmlText = lib.children("..")"
411/// fxn calls the element() member function of the Rappture.library
412///     class and returns the text to the caller
413/**
414 * Clients use this function to call the xml() member function of the
415 *          Rappture.library class and get the text of the Rappture
416 *          object lib.
417 *
418 * Notes:   If (flavor == "object") || (flavor == NULL),
419 *          1) it is the client's responsibility to increment and
420 *             decrement the reference count of the returned object
421 *             as needed.
422 *          2) the return object will need to be cast as a PyObject*
423 *             to use it.
424 *
425 *          If (flavor == "type")||(flavor == "id")||(flavor == "component"),
426 *          1) the return object will need to be case as a char*
427 *             to use it.
428 *       
429 *        The Arguments lib and pathare not optional.
430 *          If either value is NULL, NULL will be returned.
431 *
432 * Returns pointer (char*) to the c style string representing the
433 *          xml text of the Rappture object if successful, or
434 *          NULL if something goes wrong.
435 */
436
437PyObject* rpChildren_f(PyObject* lib, const char* path, const char* flavor)
438{
439    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
440    PyObject* rslt      = NULL;      /* results from fxn call */
441//    PyObject* list_item = NULL;      /* item from list of returned children */
442//    void* retVal        = NULL;      /* fxn return value */
443//    int list_size       = 0;
444//    int index           = 0;
445//    char** rslt_arr_c   = NULL;
446//    void** rslt_arr  = NULL;
447
448//    char* xmlChild = NULL;
449
450    if (lib && path) {
451       
452        // retrieve the lib.children() function
453        mbr_fxn = PyObject_GetAttrString(lib, "children");
454
455        if (mbr_fxn) {
456
457            if (PyCallable_Check(mbr_fxn)) {
458               
459                // call the lib.children() function with arguments
460                if (flavor) {
461                    rslt = PyObject_CallFunction(mbr_fxn,"(ss)", path, flavor);
462                }
463                else {
464                    rslt = PyObject_CallFunction(mbr_fxn,"(s)", path);
465                }
466
467                /*
468                if (rslt) {
469                    list_size = PyList_Size(rslt);
470                    while (index < list_size) {
471                        // list_item is a borrowed reference
472                        list_item = PyList_GetItem(rslt,index);
473                        // we cannot deallocate the results of
474                        // PyString_AsString()
475                        // printf("list item = :%x:\n", list_item);
476                        xmlChild = PyString_AsString(list_item);
477                        printf("xml = :%s:\n",xmlChild);
478                        index++;
479                    }
480                }
481                */
482
483                /*
484                if (rslt) {
485                    list_item = PyList_GetItem(rslt,0);
486                    xmlChild = PyString_AsString(list_item);
487                    printf("xml0 = :%s:\n",xmlChild);
488                    list_item = PyList_GetItem(rslt,1);
489                    xmlChild = PyString_AsString(list_item);
490                    printf("xml1 = :%s:\n",xmlChild);
491                } // rslt was null
492                */
493               
494            } // mbr_fxn was not callable
495           
496            Py_DECREF(mbr_fxn);
497        } // mbr_fxn was null
498    }
499    else {
500        // lib or path was set to NULL
501    }
502
503    return rslt;
504}
505
506/**********************************************************************/
507// FUNCTION: const char* rpGet(PyObject* lib, const char* path)
508/// fxn to mimic/implement the python call "xmlText = lib.get('...')"
509/// fxn calls the get() member function of the Rappture.library class
510///     and returns the text to the caller
511/**
512 * Clients use this function to call the get() member function of the
513 *          Rappture.library class and get the text of the Rappture
514 *          object lib.
515 *
516 * Notes: The argument (lib) is not optional. If it is NULL,
517 *          NULL will be returned.
518 *
519 * Returns pointer (const char*) to the c style string representing the
520 *          xml text provided by the path of the Rappture object if
521 *          successful, or NULL if something goes wrong.
522 *
523 *          The return value's contents should not be changed because
524 *          it is a pointer being borrowed from python's buffer space
525 *          (hence the _const_)
526 */
527const char* rpGet(PyObject* lib, const char* path)
528{
529    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
530    PyObject* rslt      = NULL;      /* results from fxn call */
531    char* retVal        = NULL;      /* return value */
532
533    if (lib) {
534        // retrieve the lib.get() function
535        mbr_fxn = PyObject_GetAttrString(lib, "get");
536
537        if (mbr_fxn) {
538
539            if (PyCallable_Check(mbr_fxn)) {
540               
541                // call the lib.get() function
542                rslt = PyObject_CallFunction(mbr_fxn,"(s)", path);
543                if (rslt) {
544                    // convert the result to c style strings
545                    retVal = PyString_AsString(rslt);
546                    // Py_DECREF(rslt);
547                }
548               
549            }
550            Py_DECREF(mbr_fxn);
551        }
552    }
553    else {
554        // lib was set to NULL
555    }
556
557    return (const char*) retVal;
558   
559}
560
561/**********************************************************************/
562// FUNCTION: void rpPut( PyObject* lib,
563//                       const char* path,
564//                       const char* value,
565//                       const char* id,
566//                       int append)
567/// fxn to mimic/implement the python call "lib.put('...')"
568/// fxn calls the put() member function of the Rappture.library class
569///     and creates user specified fields within xml document
570/**
571 * Clients use this function to call the put() member function of the
572 *          Rappture.library class and place custom text into the
573 *          Rappture object lib.
574 *
575 * Notes: The argument (lib) is not optional. If it is NULL,
576 *          NULL will be returned.
577 *
578 * Returns nothing.
579 */
580void rpPut( PyObject* lib,
581            const char* path,
582            const char* value,
583            const char* id,
584            int append )
585{
586    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
587
588    if (lib) {
589        // retrieve the lib.xml() function
590        mbr_fxn = PyObject_GetAttrString(lib, "put");
591
592        if (mbr_fxn) {
593
594            if (PyCallable_Check(mbr_fxn)) {
595                PyObject_CallFunction(mbr_fxn,"(sssi)",path,value,id,append);
596            }
597            Py_DECREF(mbr_fxn);
598        }
599    }
600    else {
601        // lib was set to NULL
602    }
603
604}
605
606/**********************************************************************/
607// FUNCTION: void rpPutObj( PyObject* lib,
608//                       const char* path,
609//                       const char* value,
610//                       const char* id,
611//                       int append)
612/// fxn to mimic/implement the python call "lib.put('...')"
613/// fxn calls the put() member function of the Rappture.library class
614///     and creates user specified fields within xml document
615/**
616 * Clients use this function to call the put() member function of the
617 *          Rappture.library class and place custom text into the
618 *          Rappture object lib.
619 *
620 * Notes: The argument (lib) is not optional. If it is NULL,
621 *          NULL will be returned.
622 *
623 * Returns nothing.
624 */
625void rpPutObj( PyObject* lib,
626            const char* path,
627            PyObject* value,
628            const char* id,
629            int append )
630{
631    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
632
633    if (lib) {
634        // retrieve the lib.xml() function
635        mbr_fxn = PyObject_GetAttrString(lib, "put");
636
637        if (mbr_fxn) {
638
639            if (PyCallable_Check(mbr_fxn)) {
640                PyObject_CallFunction(mbr_fxn,"(sOsi)",path,value,id,append);
641                // PyObject_CallFunctionObjArgs(mbr_fxn,path,value,id,append,NULL);
642            }
643            Py_DECREF(mbr_fxn);
644        }
645    }
646    else {
647        // lib was set to NULL
648    }
649
650}
651
652/**********************************************************************/
653// FUNCTION: PyObject* rpRemove(PyObject* lib, const char* path)
654/// fxn to mimic/implement the python call "lib.remove('...')"
655/// fxn calls the remove() member function of the Rappture.library class
656///     and removes the elements listed, if they exist
657/**
658 * Clients use this function to call the remove() member function of the
659 *          Rappture.library class and remove the elements of the
660 *          Rappture object lib.
661 *
662 * Notes: The argument (lib) is not optional. If it is NULL,
663 *          NULL will be returned.
664 *
665 * Returns nothin.
666 *
667 */
668PyObject* rpRemove(PyObject* lib, const char* path)
669{
670    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
671    PyObject* rslt      = NULL;      /* results from fxn call */
672   
673//    PyObject* args = NULL;
674//    PyObject* stringarg = NULL;
675
676
677    if (lib) {
678        // retrieve the lib.remove() function
679        mbr_fxn = PyObject_GetAttrString(lib, "remove");
680
681        if (mbr_fxn) {
682
683            if (PyCallable_Check(mbr_fxn)) {
684
685                // setup our arguments in a Python tuple
686                // args = PyTuple_New(1);
687                // stringarg = PyString_FromString(path);
688                // PyTuple_SetItem(args, 0, stringarg);
689
690                // call the class ... lib = Rappture.library("...")
691                // rslt = PyObject_CallObject(mbr_fxn, args);
692
693               
694                // call the lib.xml() function with no arguments
695                rslt = PyObject_CallFunction(mbr_fxn,"(s)", path);
696                // it is caller's responsibility to adjust reference count
697                // Py_DECREF(rslt);
698               
699            }
700            Py_DECREF(mbr_fxn);
701        }
702    }
703    else {
704        // lib was set to NULL
705    }
706
707    return rslt;
708   
709}
710
711/**********************************************************************/
712// FUNCTION: const char* rpXml(PyObject* lib)
713/// fxn to mimic/implement the python call "xmlText = lib.xml()"
714/// fxn calls the xml() member function of the Rappture.library class
715///     and returns the text to the caller
716/**
717 * Clients use this function to call the xml() member function of the
718 *          Rappture.library class and get the text of the Rappture
719 *          object lib.
720 *
721 * Notes: The argument (lib) is not optional. If it is NULL,
722 *          NULL will be returned.
723 *
724 * Returns pointer (char*) to the c style string representing the
725 *          xml text of the Rappture object if successful, or
726 *          NULL if something goes wrong.
727 *
728 *          return value no longer needs to be const because i copy it
729 *          to tmp space but it will need to be free'd now
730 */
731
732
733char* rpXml(PyObject* lib)
734{
735    PyObject* mbr_fxn   = NULL;      /* pointer to fxn of class lib */
736    PyObject* rslt      = NULL;      /* results from fxn call */
737    char* tmpretVal     = NULL;      /* return value */
738    char* retVal        = NULL;      /* return value */
739
740    if (lib) {
741        // retrieve the lib.xml() function
742        mbr_fxn = PyObject_GetAttrString(lib, "xml");
743
744        if (mbr_fxn) {
745
746            if (PyCallable_Check(mbr_fxn)) {
747               
748                // call the lib.xml() function
749                rslt = PyObject_CallFunction(mbr_fxn,NULL);
750                if (rslt) {
751                    // convert the result to c style strings
752                    tmpretVal = PyString_AsString(rslt);
753                    retVal = (char*) calloc(strlen(tmpretVal),sizeof(char));
754                    strcpy(retVal,tmpretVal);
755                    Py_DECREF(rslt);
756                }
757               
758            }
759            Py_DECREF(mbr_fxn);
760        }
761    }
762    else {
763        // lib was set to NULL
764    }
765
766    return retVal;
767   
768}
Note: See TracBrowser for help on using the repository browser.