Back to index

lightning-sunbird  0.9+nobinonly
TypeObject.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Python XPCOM language bindings.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * ActiveState Tool Corp.
00018  * Portions created by the Initial Developer are Copyright (C) 2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Mark Hammond <mhammond@skippinet.com.au> (original author)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 //
00039 // This code is part of the XPCOM extensions for Python.
00040 //
00041 // Written May 2000 by Mark Hammond.
00042 //
00043 // Based heavily on the Python COM support, which is
00044 // (c) Mark Hammond and Greg Stein.
00045 //
00046 // (c) 2000, ActiveState corp.
00047 
00048 #include "PyXPCOM_std.h"
00049 #include <nsIInterfaceInfoManager.h>
00050 #include <nsXPCOM.h>
00051 #include <nsISupportsPrimitives.h>
00052 
00053 
00054 static PyTypeObject PyInterfaceType_Type = {
00055        PyObject_HEAD_INIT(&PyType_Type)
00056        0,                   /* Number of items for varobject */
00057        "interface-type",                  /* Name of this type */
00058        sizeof(PyTypeObject),       /* Basic object size */
00059        0,                   /* Item size for varobject */
00060        0,                   /*tp_dealloc*/
00061        0,                   /*tp_print*/
00062        PyType_Type.tp_getattr, /*tp_getattr*/
00063        0,                   /*tp_setattr*/
00064        0,                   /*tp_compare*/
00065        PyType_Type.tp_repr, /*tp_repr*/
00066        0,                   /*tp_as_number*/
00067        0,                   /*tp_as_sequence*/
00068        0,                   /*tp_as_mapping*/
00069        0,                   /*tp_hash*/
00070        0,                   /*tp_call*/
00071        0,                   /*tp_str*/
00072        0,                   /*tp_xxx1*/
00073        0,                   /*tp_xxx2*/
00074        0,                   /*tp_xxx3*/
00075        0,                   /*tp_xxx4*/
00076        "Define the behavior of a PythonCOM Interface type.",
00077 };
00078 
00079 /*static*/ PRBool
00080 PyXPCOM_TypeObject::IsType(PyTypeObject *t)
00081 {
00082        return t->ob_type == &PyInterfaceType_Type;
00083 }
00084 
00086 //
00087 // The type methods
00088 //
00089 /*static*/PyObject *
00090 PyXPCOM_TypeObject::Py_getattr(PyObject *self, char *name)
00091 {
00092        return ((Py_nsISupports *)self)->getattr(name);
00093 }
00094 
00095 /*static*/int
00096 PyXPCOM_TypeObject::Py_setattr(PyObject *op, char *name, PyObject *v)
00097 {
00098        return ((Py_nsISupports *)op)->setattr(name, v);
00099 }
00100 
00101 // @pymethod int|Py_nsISupports|__cmp__|Implements XPCOM rules for object identity.
00102 /*static*/int
00103 PyXPCOM_TypeObject::Py_cmp(PyObject *self, PyObject *other)
00104 {
00105        // @comm NOTE: Copied from COM - have not confirmed these rules are true for XPCOM
00106        // @comm As per the XPCOM rules for object identity, both objects are queried for nsISupports, and these values compared.
00107        // The only meaningful test is for equality - the result of other comparisons is undefined
00108        // (ie, determined by the object's relative addresses in memory.
00109        nsISupports *pUnkOther;
00110        nsISupports *pUnkThis;
00111        if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
00112               return -1;
00113        if (!Py_nsISupports::InterfaceFromPyObject(other, NS_GET_IID(nsISupports), &pUnkOther, PR_FALSE)) {
00114               pUnkThis->Release();
00115               return -1;
00116        }
00117        int rc = pUnkThis==pUnkOther ? 0 :
00118               (pUnkThis < pUnkOther ? -1 : 1);
00119        pUnkThis->Release();
00120        pUnkOther->Release();
00121        return rc;
00122 }
00123 
00124 // @pymethod int|Py_nsISupports|__hash__|Implement a hash-code for the XPCOM object using XPCOM identity rules.
00125 /*static*/long PyXPCOM_TypeObject::Py_hash(PyObject *self)
00126 {
00127        // We always return the value of the nsISupports *.
00128        nsISupports *pUnkThis;
00129        if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
00130               return -1;
00131        long ret = _Py_HashPointer(pUnkThis);
00132        pUnkThis->Release();
00133        return ret;
00134 }
00135 
00136 // @method string|Py_nsISupports|__repr__|Called to create a representation of a Py_nsISupports object
00137 /*static */PyObject *
00138 PyXPCOM_TypeObject::Py_repr(PyObject *self)
00139 {
00140        // @comm The repr of this object displays both the object's address, and its attached nsISupports's address
00141        Py_nsISupports *pis = (Py_nsISupports *)self;
00142        // Try and get the IID name.
00143        char *iid_repr;
00144        nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
00145        if (iim!=nsnull)
00146               iim->GetNameForIID(&pis->m_iid, &iid_repr);
00147        if (iid_repr==nsnull)
00148               // no IIM available, or it doesnt know the name.
00149               iid_repr = pis->m_iid.ToString();
00150        // XXX - need some sort of buffer overflow.
00151        char buf[512];
00152        sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>", iid_repr, self, pis->m_obj);
00153        nsMemory::Free(iid_repr);
00154        return PyString_FromString(buf);
00155 }
00156 
00157 /*static */PyObject *
00158 PyXPCOM_TypeObject::Py_str(PyObject *self)
00159 {
00160        Py_nsISupports *pis = (Py_nsISupports *)self;
00161        nsresult rv;
00162        char *val = NULL;
00163        Py_BEGIN_ALLOW_THREADS;
00164        { // scope to kill pointer while thread-lock released.
00165        nsCOMPtr<nsISupportsCString> ss( do_QueryInterface(pis->m_obj, &rv ));
00166        if (NS_SUCCEEDED(rv))
00167               rv = ss->ToString(&val);
00168        } // end-scope 
00169        Py_END_ALLOW_THREADS;
00170        PyObject *ret;
00171        if (NS_FAILED(rv))
00172               ret = Py_repr(self);
00173        else
00174               ret = PyString_FromString(val);
00175        if (val) nsMemory::Free(val);
00176        return ret;
00177 }
00178 
00179 /* static */void
00180 PyXPCOM_TypeObject::Py_dealloc(PyObject *self)
00181 {
00182        delete (Py_nsISupports *)self;
00183 }
00184 
00185 PyXPCOM_TypeObject::PyXPCOM_TypeObject( const char *name, PyXPCOM_TypeObject *pBase, int typeSize, struct PyMethodDef* methodList, PyXPCOM_I_CTOR thector)
00186 {
00187        static const PyTypeObject type_template = {
00188               PyObject_HEAD_INIT(&PyInterfaceType_Type)
00189               0,                                           /*ob_size*/
00190               "XPCOMTypeTemplate",                         /*tp_name*/
00191               sizeof(Py_nsISupports),                 /*tp_basicsize*/
00192               0,                                           /*tp_itemsize*/
00193               Py_dealloc,                                  /* tp_dealloc */
00194               0,                                           /* tp_print */
00195               Py_getattr,                                  /* tp_getattr */
00196               Py_setattr,                                  /* tp_setattr */
00197               Py_cmp,                                      /* tp_compare */
00198               Py_repr,                                     /* tp_repr */
00199               0,                                           /* tp_as_number*/
00200               0,                                           /* tp_as_sequence */
00201               0,                                           /* tp_as_mapping */
00202               Py_hash,                                       /* tp_hash */
00203               0,                                           /* tp_call */
00204               Py_str,                                      /* tp_str */
00205        };
00206 
00207        *((PyTypeObject *)this) = type_template;
00208 
00209        chain.methods = methodList;
00210        chain.link = pBase ? &pBase->chain : NULL;
00211 
00212        baseType = pBase;
00213        ctor = thector;
00214 
00215        // cast away const, as Python doesnt use it.
00216        tp_name = (char *)name;
00217        tp_basicsize = typeSize;
00218 }
00219 
00220 PyXPCOM_TypeObject::~PyXPCOM_TypeObject()
00221 {
00222 }