Handles
Handles
This is smart pointers used by Open Cascade.
A detailed explanation on handles is given the Open Cascade documentation: Programming with Handles.
They are just references to values. So different references can point to the same object. Once all the references come out of scope, the object is destroyed.
Nim
Basic example
The following code does the following:
import occt
var aPnt:HandleGeom_CartesianPoint
aPnt = newHandle( cnew newGeomCartesianPoint(1.1, 2.2, 3.3) )
echo `*`(aPnt).x
`*`(aPnt).setY(1.3)
echo `*`(aPnt).y
- The code
var aPnt:HandleGeom_CartesianPoint
creates the variableaPnt
with typeHandleGeom_CartesianPoint
. Bear in mind thatHandleGeom_CartesianPoint
is an alias for:Handle[CartesianPoint]
. - The code
cnew newGeomCartesianPoint(0.0,0.0,0.0)
creates aptr Geom_CartesianPoint
. This can be automatically converted toHandleGeom_CartesianPoint
thanks to a converter defined instandard_handle.nim
. - The code
aPnt = newHandle( cnew newGeomCartesianPoint(0.0,0.0,0.0) )
creates aHandleGeom_CartesianPoint
from theptr Geom_CartesianPoint
. - The code:
is used to show the content of
echo `*`(aPnt).x
aPnt
through the handle. For that purpose, we use the operator*
which convertsHandleGeom_CartesianPoint
intovar Geom_CartesianPoint
. - The code:
is used for assigment by means of the handle.
*`(aPnt).setY(1.3)`
In the above example, memory is handled by C++ side part of the history.
One to many example
The following example shows how two handles point to the same object:
import occt
# Create the pointer to the object
var aPntPtr = cnew newGeomCartesianPoint(1.1, 2.2, 3.3)
# Create handles for the object
var aPntHandle1, aPntHandle2: HandleGeom_CartesianPoint
aPntHandle1 = newHandle( aPntPtr )
aPntHandle2 = newHandle( aPntPtr )
# We can now access to the same object through different handles
assert `*`(aPntHandle1).x == `*`(aPntHandle2).x
assert `*`(aPntHandle1).y == `*`(aPntHandle2).y
assert `*`(aPntHandle1).z == `*`(aPntHandle2).z
# If we modify something using one handle, the other can see it.
`*`(aPntHandle1).setY(1.3)
assert `*`(aPntHandle1).y == `*`(aPntHandle2).y
echo `*`(aPntHandle1).y
echo "All assertions were true!!"
Wayforward
With a couple of function is very easy to simplify the coding. The first one, creates a constructor for handles. The second one is a converter that enables using the handle as if it were the object itself:
import occt
proc newPointCartesian[X,Y,Z:SomeNumber](x:X; y:Y, z:Z):HandleGeom_CartesianPoint =
newHandle( cnew newGeomCartesianPoint(x.cfloat, y.cfloat, z.cfloat) )
converter toGeom_CartesianPoint*(tmp:HandleGeom_CartesianPoint):var Geom_CartesianPoint =
`*`(tmp)
# Create the pointer to the object
var aPnt2:HandleGeom_CartesianPoint
var aPnt1 = newPointCartesian(1, 2.2, 3.3)
echo aPnt1.x, " ", aPnt1.y, " ", aPnt1.z
echo "aPnt is null: ", aPnt1.isNull, " ", aPnt2.isNull
aPnt2 = aPnt1
echo aPnt2.y
echo aPnt1.y
aPnt1.setY(5.5)
echo aPnt2.y
echo aPnt1.y
Future ideas:
Type conformity
https://dev.opencascade.org/doc/overview/html/occt_user_guides__foundation_classes.html#autotoc_md64
This can be implemented by means of something like:
converter toGeom_Point*(tmp:HandleGeom_CartesianPoint):HandleGeom_Point {.importcpp:"(@)", header:"Geom_Point.hxx",cdecl.}
So that the following works:
var aPnt1:HandleGeom_Point
var aPnt2:HandleGeom_CartesianPoint
aPnt2 = newPointCartesian(1, 2.2, 3.3)
aPnt1 = aPnt2 # This creates automatic conversion thanks to C++ side type conformity (it would be wrong in Nim). Thanks to the converter.
Proposal
-
The type used in Nim could be directly the handle.
-
Needs to be defined how to work with inheritance:
- Option 1: inheritance between handles.
- Option 2: using types as a mean to simulate inheritance.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.