From C++ to C#
NetOcc is generated from OCCT's headers: a C++ signature decides its C# signature. With the rules below, OCCT's reference manual and C++ code translate line by line.
What a C++ type becomes
flowchart LR
transient["Standard_Transient subclass<br/>Geom_Circle, AIS_Shape"] -->|holds one reference| c1["C# class"]
other["any other class<br/>TopoDS_Shape, BRepPrimAPI_MakeBox"] -->|owns the object| c2["C# class"]
value["fixed-layout value<br/>gp_Pnt, Bnd_Box, Quantity_Color"] -->|same memory layout| c3["C# struct"]
enumeration["enum"] --> c4["C# enum"]
functions["namespace functions<br/>TopoDS::Face"] --> c5["static class"]
All classes are IDisposable, see Object lifetimes.
Names
| C++ | C# |
|---|---|
package gp, class gp_Pnt |
namespace OCC.Core.gp, gp_Pnt |
nested Geom_Curve::ResD1 |
Geom_Curve_ResD1: scopes joined by _ |
namespace functions TopoDS::Face(shape) |
a static class: TopoDS.Face(shape) |
GeomAbs_CurveType enum |
a C# enum with OCCT's values and underlying type |
typedef NCollection_Array1<gp_Pnt> TColgp_Array1OfPnt |
class TColgp_Array1OfPnt |
a parameter named like a C# keyword (string) |
suffixed: string_ |
Handles
Handle(T) is T: the proxy holds one reference on the object, and null is a null handle. A C# cast never reaches the C++ object, so casts go through DownCast:
Geom_Curve curve = new Geom_Circle(new gp_Ax2(), 10); // a Handle(Geom_Curve) in C++
var circle = Geom_Circle.DownCast(curve); // the circle, or null
var line = Geom_Line.DownCast(curve); // null: it isn't a line
var radius = circle?.Radius();
Value types
All of gp, Bnd_Box, Quantity_Color, Poly_Triangle and a few more are C# structs with OCCT's memory layout: no allocation, passed by pointer to OCCT. Their methods run OCCT's code, and OCCT's arithmetic operators (+, -, *, /, ^) are C# operators. Other classes have none; OCCT's operators mostly repeat a named member, which they have (Multiplied, IsEqual, Value):
var sum = new gp_Vec(1, 0, 0) + new gp_Vec(0, 1, 0); // operator+
var scaled = sum * 2; // operator*
var dot = sum * new gp_Vec(1, 0, 0); // gp_Vec * gp_Vec: the dot product
var cross = new gp_Vec(1, 0, 0) ^ new gp_Vec(0, 1, 0); // operator^: the cross product
Plain data (OCCT 8's evaluation results) is a struct with public fields: curve.EvalD1(u).Point.
Parameters
| C++ | C# |
|---|---|
T& of a number, enum or struct |
ref T (never out: OCCT may read it first) |
const T& of a struct |
in T |
T& or const T& of a class |
the proxy |
Handle(T)& |
ref T: the variable gets the object OCCT puts there |
T* of numbers or structs |
a C# array, pinned for the call (double[], gp_Pnt[]) |
T* of a class |
the proxy, null for nullptr |
void*, function pointers, pointers OCCT keeps |
IntPtr |
int (&)[3] |
an array of exactly three |
Message_ProgressRange at the end, defaulted |
left out |
| default arguments | overloads |
// Standard_Real& First, Standard_Real& Last: ref, initialized first
double first = 0, last = 0;
var curve = BRep_Tool.Curve(edge, ref first, ref last);
// Bnd_Box& (a struct): ref as well
var bounds = new Bnd_Box();
OCC.Core.BRepBndLib.BRepBndLib.Add(box, ref bounds);
A member returning T& of a number, enum or struct is a C# ref return, read and written in place:
// Standard_Real& Value(int, int): a ref return, read and written in place
var matrix = new math_Matrix(1, 2, 1, 2, 0.0);
matrix.Value(1, 2) = 5.0;
ref var cell = ref matrix.Value(2, 1);
cell = 7.0;
A member returning a class by reference gives a proxy that borrows the object and keeps its owner alive. So does a copy that refers to its owner, such as BRepGraph.Topo()'s view of the graph or V3d_Viewer.ActiveViewIterator()'s iterator over the viewer's views. A member returning *this for chaining returns void.
Collections
OCCT's arrays, lists, sequences and maps are C# classes named by OCCT's aliases, IEnumerable<T>, with indexers using OCCT's bounds:
// arrays from C# arrays, numbered from 1; indexers use OCCT's bounds
var points =
new TColgp_Array1OfPnt([new gp_Pnt(0, 0, 0), new gp_Pnt(10, 0, 0), new gp_Pnt(10, 10, 0)]);
var second = points[2];
gp_Pnt[] copy = points.ToArray();
// or with bounds of your choice
var weights = new TColStd_Array1OfReal(0, 2);
weights[0] = 1.0;
// sequences grow, and count from 1
var sequence = new TColStd_SequenceOfReal();
sequence.Append(1.5);
sequence.Append(2.5);
var sum = sequence.Sum(); // IEnumerable<double>: LINQ works
// maps: an indexed map numbers its keys from 1
var faces = new TopTools_IndexedMapOfShape();
TopExp.MapShapes(new BRepPrimAPI_MakeBox(1, 1, 1).Shape(), TopAbs_ShapeEnum.TopAbs_FACE, faces);
var index = faces.FindIndex(faces[3]); // 3
| Collection | Indexed | From |
|---|---|---|
*_Array1Of*, *_Array2Of* |
by the bounds given (Lower() to Upper()) |
a C# array: 1 |
*_SequenceOf* |
yes | 1 |
*_ListOf* |
no: enumerate, First(), Last() |
|
*_IndexedMapOf*, *_IndexedDataMapOf* |
by number, and FindIndex(key) |
1 |
*_MapOf* |
no: a set, Contains(key) |
|
*_DataMapOf* |
by key, ContainsKey(key); enumerates KeyValuePairs |
The handle-managed variants (TColgp_HArray1OfPnt) derive from their collection. Count is OCCT's Extent() or Length(). A bad index throws:
Action beyond = () => _ = points[4]; // Standard_OutOfRange, as an OcctException
Strings and the standard library
// Standard_GUID: System.Guid
Guid id = TDataStd_Real.GetID();
// std::optional<gp_Pnt>: gp_Pnt?, null for an empty box
gp_Pnt? centre = new Bnd_Box().Center();
// TCollection_AsciiString and const char*: string
Geom_Curve curve = new Geom_Circle(new gp_Ax2(), 1);
string name = curve.DynamicType().Name(); // "Geom_Circle"
| C++ | C# |
|---|---|
const char*, TCollection_AsciiString, std::string, std::string_view |
string (UTF-8) |
const char16_t*, TCollection_ExtendedString |
string (UTF-16) |
Standard_GUID |
System.Guid |
std::array<double, 3> |
double[] |
std::optional<T> |
T? |
std::pair<A, B> |
a class with First and Second |
std::bitset<N> |
ulong |
std::complex<double> |
OCC.Core.Complex |
std::ostream&, std::istream& |
System.IO.Stream, see Files |
char |
byte (its bits, not a character) |
char32_t |
uint (a code point) |
size_t |
ulong; on x86 a larger value throws OcctException |
Errors
OCCT's Standard_Failure and its subclasses arrive as OcctException, see Errors.
Deprecated and left out
What OCCT marks deprecated is wrapped and [Obsolete]. What can't be mapped is left out, each member with its reason in Skipped members: members OCCT declares but never exports, raw pointers into structs, streams OCCT would keep beyond a call, template instances C# can't create or name.