diff options
Diffstat (limited to 'source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp')
-rw-r--r-- | source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp | 458 |
1 files changed, 284 insertions, 174 deletions
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp index 14e6f143b84..0d0a772b4e5 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp @@ -10,7 +10,9 @@ extern "C" { /////////////////////////////////////////////////////////////////////////////////////////// -static char SVertex___doc__[] = +/*----------------------SVertex methods ----------------------------*/ + +PyDoc_STRVAR(SVertex_doc, "Class hierarchy: :class:`Interface0D` > :class:`SVertex`\n" "\n" "Class to define a vertex of the embedding.\n" @@ -33,32 +35,29 @@ static char SVertex___doc__[] = " :arg iPoint3D: A three-dimensional vector.\n" " :type iPoint3D: :class:`mathutils.Vector`\n" " :arg id: An Id object.\n" -" :type id: :class:`Id`\n"; - -//------------------------INSTANCE METHODS ---------------------------------- +" :type id: :class:`Id`"); -static int SVertex___init__(BPy_SVertex *self, PyObject *args, PyObject *kwds) +static int SVertex_init(BPy_SVertex *self, PyObject *args, PyObject *kwds) { PyObject *py_point = 0; BPy_Id *py_id = 0; - - if (! PyArg_ParseTuple(args, "|OO!", &py_point, &Id_Type, &py_id) ) - return -1; + if (!PyArg_ParseTuple(args, "|OO!", &py_point, &Id_Type, &py_id)) + return -1; - if( !py_point ) { + if (!py_point) { self->sv = new SVertex(); - } else if( !py_id && BPy_SVertex_Check(py_point) ) { + } else if (!py_id && BPy_SVertex_Check(py_point)) { self->sv = new SVertex( *(((BPy_SVertex *)py_point)->sv) ); - } else if( py_point && py_id ) { + } else if (py_point && py_id) { Vec3r *v = Vec3r_ptr_from_PyObject(py_point); - if( !v ) { + if (!v) { PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); return -1; } - self->sv = new SVertex( *v, *(py_id->id) ); + self->sv = new SVertex(*v, *(py_id->id)); delete v; } else { @@ -68,192 +67,310 @@ static int SVertex___init__(BPy_SVertex *self, PyObject *args, PyObject *kwds) self->py_if0D.if0D = self->sv; self->py_if0D.borrowed = 0; - + return 0; } -static char SVertex_normals___doc__[] = -".. method:: normals()\n" +PyDoc_STRVAR(SVertex_add_normal_doc, +".. method:: add_normal(n)\n" "\n" -" Returns the normals for this Vertex as a list. In a smooth surface,\n" -" a vertex has exactly one normal. In a sharp surface, a vertex can\n" -" have any number of normals.\n" +" Adds a normal to the SVertex's set of normals. If the same normal\n" +" is already in the set, nothing changes.\n" "\n" -" :return: A list of normals.\n" -" :rtype: List of :class:`mathutils.Vector` objects\n"; +" :arg n: A three-dimensional vector.\n" +" :type n: :class:`mathutils.Vector`, list or tuple of 3 real numbers"); -static PyObject * SVertex_normals( BPy_SVertex *self ) { - PyObject *py_normals; - set< Vec3r > normals; - - py_normals = PyList_New(0); - normals = self->sv->normals(); - - for( set< Vec3r >::iterator set_iterator = normals.begin(); set_iterator != normals.end(); set_iterator++ ) { - Vec3r v( *set_iterator ); - PyList_Append( py_normals, Vector_from_Vec3r(v) ); +static PyObject *SVertex_add_normal( BPy_SVertex *self , PyObject *args) { + PyObject *py_normal; + + if (!PyArg_ParseTuple(args, "O", &py_normal)) + return NULL; + Vec3r *n = Vec3r_ptr_from_PyObject(py_normal); + if (!n) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; } - - return py_normals; + self->sv->AddNormal(*n); + delete n; + + Py_RETURN_NONE; } -static char SVertex_normalsSize___doc__[] = -".. method:: normalsSize()\n" +PyDoc_STRVAR(SVertex_add_fedge_doc, +".. method:: add_fedge(fe)\n" "\n" -" Returns the number of different normals for this vertex.\n" +" Add an FEdge to the list of edges emanating from this SVertex.\n" "\n" -" :return: The number of normals.\n" -" :rtype: int\n"; +" :arg fe: An FEdge.\n" +" :type fe: :class:`FEdge`"); + +static PyObject *SVertex_add_fedge( BPy_SVertex *self , PyObject *args) { + PyObject *py_fe; -static PyObject * SVertex_normalsSize( BPy_SVertex *self ) { - return PyLong_FromLong( self->sv->normalsSize() ); + if (!PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe)) + return NULL; + + self->sv->AddFEdge(((BPy_FEdge *)py_fe)->fe); + + Py_RETURN_NONE; } -static char SVertex_viewvertex___doc__[] = -".. method:: viewvertex()\n" -"\n" -" If this SVertex is also a ViewVertex, this method returns the\n" -" ViewVertex. None is returned otherwise.\n" -"\n" -" :return: The ViewVertex object.\n" -" :rtype: :class:`ViewVertex`\n"; +// virtual bool operator== (const SVertex &iBrother) -static PyObject * SVertex_viewvertex( BPy_SVertex *self ) { - ViewVertex *vv = self->sv->viewvertex(); - if( vv ) - return Any_BPy_ViewVertex_from_ViewVertex( *vv ); +static PyMethodDef BPy_SVertex_methods[] = { + {"add_normal", (PyCFunction)SVertex_add_normal, METH_VARARGS, SVertex_add_normal_doc}, + {"add_fedge", (PyCFunction)SVertex_add_fedge, METH_VARARGS, SVertex_add_fedge_doc}, + {NULL, NULL, 0, NULL} +}; - Py_RETURN_NONE; +/*----------------------mathutils callbacks ----------------------------*/ + +/* subtype */ +#define MATHUTILS_SUBTYPE_POINT3D 1 +#define MATHUTILS_SUBTYPE_POINT2D 2 + +static int SVertex_mathutils_check(BaseMathObject *bmo) +{ + if (!BPy_SVertex_Check(bmo->cb_user)) + return -1; + return 0; } -static char SVertex_setPoint3D___doc__[] = -".. method:: setPoint3D(p)\n" -"\n" -" Sets the 3D coordinates of the SVertex.\n" -"\n" -" :arg p: A three-dimensional vector.\n" -" :type p: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; +static int SVertex_mathutils_get(BaseMathObject *bmo, int subtype) +{ + BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user; + switch (subtype) { + case MATHUTILS_SUBTYPE_POINT3D: + bmo->data[0] = self->sv->getX(); + bmo->data[1] = self->sv->getY(); + bmo->data[2] = self->sv->getZ(); + break; + case MATHUTILS_SUBTYPE_POINT2D: + bmo->data[0] = self->sv->getProjectedX(); + bmo->data[1] = self->sv->getProjectedY(); + bmo->data[2] = self->sv->getProjectedZ(); + break; + default: + return -1; + } + return 0; +} -static PyObject *SVertex_setPoint3D( BPy_SVertex *self , PyObject *args) { - PyObject *py_point; +static int SVertex_mathutils_set(BaseMathObject *bmo, int subtype) +{ + BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user; + switch (subtype) { + case MATHUTILS_SUBTYPE_POINT3D: + { + Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]); + self->sv->setPoint3D(p); + } + break; + case MATHUTILS_SUBTYPE_POINT2D: + { + Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]); + self->sv->setPoint2D(p); + } + break; + default: + return -1; + } + return 0; +} - if(!( PyArg_ParseTuple(args, "O", &py_point) )) - return NULL; - Vec3r *v = Vec3r_ptr_from_PyObject(py_point); - if( !v ) { - PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); - return NULL; +static int SVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index) +{ + BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user; + switch (subtype) { + case MATHUTILS_SUBTYPE_POINT3D: + switch (index) { + case 0: bmo->data[0] = self->sv->getX(); break; + case 1: bmo->data[1] = self->sv->getY(); break; + case 2: bmo->data[2] = self->sv->getZ(); break; + default: + return -1; + } + break; + case MATHUTILS_SUBTYPE_POINT2D: + switch (index) { + case 0: bmo->data[0] = self->sv->getProjectedX(); break; + case 1: bmo->data[1] = self->sv->getProjectedY(); break; + case 2: bmo->data[2] = self->sv->getProjectedZ(); break; + default: + return -1; + } + break; + default: + return -1; } - self->sv->setPoint3D( *v ); - delete v; + return 0; +} - Py_RETURN_NONE; +static int SVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index) +{ + BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user; + switch (subtype) { + case MATHUTILS_SUBTYPE_POINT3D: + { + Vec3r p(self->sv->point3D()); + p[index] = bmo->data[index]; + self->sv->setPoint3D(p); + } + break; + case MATHUTILS_SUBTYPE_POINT2D: + { + Vec3r p(self->sv->point2D()); + p[index] = bmo->data[index]; + self->sv->setPoint2D(p); + } + break; + default: + return -1; + } + return 0; } -static char SVertex_setPoint2D___doc__[] = -".. method:: setPoint2D(p)\n" -"\n" -" Sets the 2D projected coordinates of the SVertex.\n" +static Mathutils_Callback SVertex_mathutils_cb = { + SVertex_mathutils_check, + SVertex_mathutils_get, + SVertex_mathutils_set, + SVertex_mathutils_get_index, + SVertex_mathutils_set_index +}; + +static unsigned char SVertex_mathutils_cb_index = -1; + +void SVertex_mathutils_register_callback() +{ + SVertex_mathutils_cb_index = Mathutils_RegisterCallback(&SVertex_mathutils_cb); +} + +/*----------------------SVertex get/setters ----------------------------*/ + +PyDoc_STRVAR(SVertex_point_3d_doc, +"The 3D coordinates of the SVertex.\n" "\n" -" :arg p: A three-dimensional vector.\n" -" :type p: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; +":type: mathutils.Vector"); -static PyObject *SVertex_setPoint2D( BPy_SVertex *self , PyObject *args) { - PyObject *py_point; +static PyObject *SVertex_point_3d_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + return Vector_CreatePyObject_cb((PyObject *)self, 3, SVertex_mathutils_cb_index, MATHUTILS_SUBTYPE_POINT3D); +} - if(!( PyArg_ParseTuple(args, "O", &py_point) )) - return NULL; - Vec3r *v = Vec3r_ptr_from_PyObject(py_point); - if( !v ) { - PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); - return NULL; +static int SVertex_point_3d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure)) +{ + float v[3]; + if (!float_array_from_PyObject(value, v, 3)) { + PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector"); + return -1; } - self->sv->setPoint2D( *v ); - delete v; - - Py_RETURN_NONE; + Vec3r p(v[0], v[1], v[2]); + self->sv->setPoint3D(p); + return 0; } -static char SVertex_AddNormal___doc__[] = -".. method:: AddNormal(n)\n" -"\n" -" Adds a normal to the SVertex's set of normals. If the same normal\n" -" is already in the set, nothing changes.\n" +PyDoc_STRVAR(SVertex_point_2d_doc, +"The projected 3D coordinates of the SVertex.\n" "\n" -" :arg n: A three-dimensional vector.\n" -" :type n: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; +":type: mathutils.Vector"); -static PyObject *SVertex_AddNormal( BPy_SVertex *self , PyObject *args) { - PyObject *py_normal; +static PyObject *SVertex_point_2d_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + return Vector_CreatePyObject_cb((PyObject *)self, 3, SVertex_mathutils_cb_index, MATHUTILS_SUBTYPE_POINT2D); +} - if(!( PyArg_ParseTuple(args, "O", &py_normal) )) - return NULL; - Vec3r *n = Vec3r_ptr_from_PyObject(py_normal); - if( !n ) { - PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); - return NULL; +static int SVertex_point_2d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure)) +{ + float v[3]; + if (!float_array_from_PyObject(value, v, 3)) { + PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector"); + return -1; } - self->sv->AddNormal( *n ); - delete n; - - Py_RETURN_NONE; + Vec3r p(v[0], v[1], v[2]); + self->sv->setPoint2D(p); + return 0; } -static char SVertex_setId___doc__[] = -".. method:: setId(id)\n" -"\n" -" Sets the identifier of the SVertex.\n" +PyDoc_STRVAR(SVertex_id_doc, +"The Id of this SVertex.\n" "\n" -" :arg id: The identifier.\n" -" :type id: :class:`Id`\n"; +":type: :class:`Id`"); -static PyObject *SVertex_setId( BPy_SVertex *self , PyObject *args) { - BPy_Id *py_id; +static PyObject *SVertex_id_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + Id id(self->sv->getId()); + return BPy_Id_from_Id(id); // return a copy +} - if( !PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ) - return NULL; +static int SVertex_id_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure)) +{ + if (!BPy_Id_Check(value)) { + PyErr_SetString(PyExc_TypeError, "value must be an Id"); + return -1; + } + self->sv->setId(*(((BPy_Id *)value)->id)); + return 0; +} - self->sv->setId( *(py_id->id) ); +PyDoc_STRVAR(SVertex_normals_doc, +"The normals for this Vertex as a list. In a sharp surface, an SVertex\n" +"has exactly one normal. In a smooth surface, an SVertex can have any\n" +"number of normals.\n" +"\n" +":type: list of :class:`mathutils.Vector` objects"); - Py_RETURN_NONE; +static PyObject *SVertex_normals_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + PyObject *py_normals; + set< Vec3r > normals; + + py_normals = PyList_New(0); + normals = self->sv->normals(); + for (set< Vec3r >::iterator set_iterator = normals.begin(); set_iterator != normals.end(); set_iterator++) { + Vec3r v(*set_iterator); + PyList_Append(py_normals, Vector_from_Vec3r(v)); + } + return py_normals; } -static char SVertex_AddFEdge___doc__[] = -".. method:: AddFEdge(fe)\n" -"\n" -" Add an FEdge to the list of edges emanating from this SVertex.\n" +PyDoc_STRVAR(SVertex_normals_size_doc, +"The number of different normals for this SVertex.\n" "\n" -" :arg fe: An FEdge.\n" -" :type fe: :class:`FEdge`\n"; +":type: int"); -static PyObject *SVertex_AddFEdge( BPy_SVertex *self , PyObject *args) { - PyObject *py_fe; +static PyObject *SVertex_normals_size_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + return PyLong_FromLong(self->sv->normalsSize()); +} - if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) )) - return NULL; - - self->sv->AddFEdge( ((BPy_FEdge *) py_fe)->fe ); +PyDoc_STRVAR(SVertex_viewvertex_doc, +"If this SVertex is also a ViewVertex, this property refers to the\n" +"ViewVertex, and None otherwise.\n" +":type: :class:`ViewVertex`"); +static PyObject *SVertex_viewvertex_get(BPy_SVertex *self, void *UNUSED(closure)) +{ + ViewVertex *vv = self->sv->viewvertex(); + if (vv) + return Any_BPy_ViewVertex_from_ViewVertex(*vv); Py_RETURN_NONE; } -static char SVertex_curvatures___doc__[] = -".. method:: curvatures()\n" +PyDoc_STRVAR(SVertex_curvatures_doc, +"Curvature information expressed in the form of a seven-element tuple\n" +"(K1, e1, K2, e2, Kr, er, dKr), where K1 and K2 are scalar values\n" +"representing the first (maximum) and second (minimum) principal\n" +"curvatures at this SVertex, respectively; e1 and e2 are\n" +"three-dimensional vectors representing the first and second principal\n" +"directions, i.e. the directions of the normal plane where the\n" +"curvature takes its maximum and minimum values, respectively; and Kr,\n" +"er and dKr are the radial curvature, radial direction, and the\n" +"derivative of the radial curvature at this SVertex, repectively.\n" "\n" -" Returns curvature information in the form of a seven-element tuple\n" -" (K1, e1, K2, e2, Kr, er, dKr), where K1 and K2 are scalar values\n" -" representing the first (maximum) and second (minimum) principal\n" -" curvatures at this SVertex, respectively; e1 and e2 are\n" -" three-dimensional vectors representing the first and second principal\n" -" directions, i.e. the directions of the normal plane where the\n" -" curvature takes its maximum and minimum values, respectively; and Kr,\n" -" er and dKr are the radial curvature, radial direction, and the\n" -" derivative of the radial curvature at this SVertex, repectively.\n" -" :return: curvature information expressed by a seven-element tuple\n" -" (K1, e1, K2, e2, Kr, er, dKr).\n" -" :rtype: tuple\n"; - -static PyObject *SVertex_curvatures( BPy_SVertex *self , PyObject *args) { +":type: tuple"); + +static PyObject *SVertex_curvatures_get(BPy_SVertex *self, void *UNUSED(closure)) +{ const CurvatureInfo *info = self->sv->getCurvatureInfo(); if (!info) Py_RETURN_NONE; @@ -261,31 +378,25 @@ static PyObject *SVertex_curvatures( BPy_SVertex *self , PyObject *args) { Vec3r e2(info->e2.x(), info->e2.y(), info->e2.z()); Vec3r er(info->er.x(), info->er.y(), info->er.z()); PyObject *retval = PyTuple_New(7); - PyTuple_SET_ITEM( retval, 0, PyFloat_FromDouble(info->K1)); - PyTuple_SET_ITEM( retval, 2, Vector_from_Vec3r(e1)); - PyTuple_SET_ITEM( retval, 1, PyFloat_FromDouble(info->K2)); - PyTuple_SET_ITEM( retval, 3, Vector_from_Vec3r(e2)); - PyTuple_SET_ITEM( retval, 4, PyFloat_FromDouble(info->Kr)); - PyTuple_SET_ITEM( retval, 5, Vector_from_Vec3r(er)); - PyTuple_SET_ITEM( retval, 6, PyFloat_FromDouble(info->dKr)); + PyTuple_SET_ITEM(retval, 0, PyFloat_FromDouble(info->K1)); + PyTuple_SET_ITEM(retval, 2, Vector_from_Vec3r(e1)); + PyTuple_SET_ITEM(retval, 1, PyFloat_FromDouble(info->K2)); + PyTuple_SET_ITEM(retval, 3, Vector_from_Vec3r(e2)); + PyTuple_SET_ITEM(retval, 4, PyFloat_FromDouble(info->Kr)); + PyTuple_SET_ITEM(retval, 5, Vector_from_Vec3r(er)); + PyTuple_SET_ITEM(retval, 6, PyFloat_FromDouble(info->dKr)); return retval; } -// virtual bool operator== (const SVertex &iBrother) -// ViewVertex * viewvertex () - -/*----------------------SVertex instance definitions ----------------------------*/ -static PyMethodDef BPy_SVertex_methods[] = { - {"normals", ( PyCFunction ) SVertex_normals, METH_NOARGS, SVertex_normals___doc__}, - {"normalsSize", ( PyCFunction ) SVertex_normalsSize, METH_NOARGS, SVertex_normalsSize___doc__}, - {"viewvertex", ( PyCFunction ) SVertex_viewvertex, METH_NOARGS, SVertex_viewvertex___doc__}, - {"setPoint3D", ( PyCFunction ) SVertex_setPoint3D, METH_VARARGS, SVertex_setPoint3D___doc__}, - {"setPoint2D", ( PyCFunction ) SVertex_setPoint2D, METH_VARARGS, SVertex_setPoint2D___doc__}, - {"AddNormal", ( PyCFunction ) SVertex_AddNormal, METH_VARARGS, SVertex_AddNormal___doc__}, - {"setId", ( PyCFunction ) SVertex_setId, METH_VARARGS, SVertex_setId___doc__}, - {"AddFEdge", ( PyCFunction ) SVertex_AddFEdge, METH_VARARGS, SVertex_AddFEdge___doc__}, - {"curvatures", ( PyCFunction ) SVertex_curvatures, METH_NOARGS, SVertex_curvatures___doc__}, - {NULL, NULL, 0, NULL} +static PyGetSetDef BPy_SVertex_getseters[] = { + {(char *)"point_3d", (getter)SVertex_point_3d_get, (setter)SVertex_point_3d_set, (char *)SVertex_point_3d_doc, NULL}, + {(char *)"point_2d", (getter)SVertex_point_2d_get, (setter)SVertex_point_2d_set, (char *)SVertex_point_2d_doc, NULL}, + {(char *)"id", (getter)SVertex_id_get, (setter)SVertex_id_set, (char *)SVertex_id_doc, NULL}, + {(char *)"normals", (getter)SVertex_normals_get, (setter)NULL, (char *)SVertex_normals_doc, NULL}, + {(char *)"normals_size", (getter)SVertex_normals_size_get, (setter)NULL, (char *)SVertex_normals_size_doc, NULL}, + {(char *)"viewvertex", (getter)SVertex_viewvertex_get, (setter)NULL, (char *)SVertex_viewvertex_doc, NULL}, + {(char *)"curvatures", (getter)SVertex_curvatures_get, (setter)NULL, (char *)SVertex_curvatures_doc, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; /*-----------------------BPy_SVertex type definition ------------------------------*/ @@ -310,7 +421,7 @@ PyTypeObject SVertex_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - SVertex___doc__, /* tp_doc */ + SVertex_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ @@ -319,13 +430,13 @@ PyTypeObject SVertex_Type = { 0, /* tp_iternext */ BPy_SVertex_methods, /* tp_methods */ 0, /* tp_members */ - 0, /* tp_getset */ + BPy_SVertex_getseters, /* tp_getset */ &Interface0D_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)SVertex___init__, /* tp_init */ + (initproc)SVertex_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; @@ -335,4 +446,3 @@ PyTypeObject SVertex_Type = { #ifdef __cplusplus } #endif - |