Basics
Library organization
Modules and toolkits
OCCT는 여러 module들로 구성됨.
첫 module - foundation classes.
한 module은 여러 toolkit (실행, 리소스)으로 구성됨.
한 toolkit은 하나의 .so 혹은 .dll
Packages
class들과 의미론적 연결.
e.g. geometry package - Point, Line, Circle classes.
class명 앞에 접두어로 package명 붙임. (e.g. Geom_Circle)
- Enumerations
- Object classes
- Exceptions
- Pointers

Contents of a package
Classes
Inheritance
Data Types
- Data types manipulated by handle (or reference)
- Data types manipulated by value - primitive

Manipulation of data types
Primitive Types
- Standard_Boolean - Standard_True, Standard_False.
- Standard_Character - ASCII character.
- Standard_ExtCharacter - extended character.
- Standard_Integer
- Standard_Real
- Standard_ShortReal
- Standard_CString - literal constants
- Standard_ExtString - extended string.
- Standard_Address - a byte address of undetermined size.
Standard package.
| C++ Types | OCCT Types | 비고 |
| int | Standard_Integer | |
| double | Standard_Real | |
| float | Standard_ShortReal | |
| bool | Standard_Boolean | |
| char | Standard_Character | UTF-8 |
| char16_t | Standard_Utf16Char | UTF-16 |
| char* | Standard_CString | UTF-8 |
| void* | Standard_Address | |
| char16_t* | Standard_ExtString | UTF-16 |
Types manipulated by value
- Primitive types
- Enumerated types
- Types defined by classes not inheriting from Standard_Transient.

Manipulation of a data type by value
Types manipulated by reference (handle)
- classes inheriting from the Standard_Transient.

Manipulation of a data type by reference
When is it necessary to use a handle?
Programming with Handles
Handle Definition
smart pointer.
Organization of Classes
reference counter를 제공하는 Standard_Transient에서 상속.
핸들을 정의하는 템플릿 클래스 : opencascade::handle<>
전처리기 매크로 : Handle()
Handle(Geom_Line) aLine; // "Handle(Geom_Line)" is expanded to "opencascade::handle<Geom_Line>"
접두어 Handle_ 이 붙은 typedef도 제공됨.
Handle_Geom_Line aLine; // "Handle_Geom_Line" is typedef to "opencascade::handle<Geom_Line>"
Using a Handle
handle 초기값은 null.
IsNull( ), Nullify( )
Type Management
RTTI 사용
Standard_Type.hxx 가 제공하는 2가지 매크로
- inline variant (간편하지만 binary가 커질 수 있음.)
#include <Geom_Surface.hxx>
class Appli_ExtSurface : public Geom_Surface
{
. . .
public:
DEFINE_STANDARD_RTTIEXT(Appli_ExtSurface,Geom_Surface)
};
- Out-of line variant
In Appli_ExtSurface.hxx file:
#include <Geom_Surface.hxx>
class Appli_ExtSurface : public Geom_Surface
{
. . .
public:
DEFINE_STANDARD_RTTIEXT(Appli_ExtSurface,Geom_Surface)
};
In Appli_ExtSurface.cxx file:
#include <Appli_ExtSurface.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Appli_ExtSurface,Geom_Surface)
사용 예
if (aCurve->IsKind(STANDARD_TYPE(Geom_Line))) // equivalent to "if (dynamic_cast<Geom_Line>(aCurve.get()) != 0)"
{
...
}
Type Conformity
up cast
Explicit Type Conversion
down case (safe cast)
Handle(Geom_Point) aPnt1;
Handle(Geom_CartesianPoint) aPnt2, aPnt3;
aPnt2 = new Geom_CartesianPoint();
aPnt1 = aPnt2; // OK, standard assignment
aPnt3 = Handle(Geom_CartesianPoint)::DownCast (aPnt1);
// OK, the actual type of aPnt1 is Geom_CartesianPoint, although the static type of the handle is Geom_Point
e.g. Standard_Transient에서 상속받은 A, B,
Handle(A) a;
Handle(B) b;
Handle(Standard_Transient) t;
TColStd_SequenceOfTransient aSeq;
a = new A();
aSeq.Append (a);
b = new B();
aSeq.Append (b);
t = aSeq.Value (1);
// here, you cannot write:
// a = t; // ERROR !
// so you downcast:
a = Handle (A)::Downcast (t)
if (!a.IsNull())
{
// types are compatible, you can use a
}
else
{
// the types are incompatible
}
Using Handles to Create Objects
생성할 때는 new 사용.
delete는 쓰지 말 것. (참조 없으면 자동 소멸됨.)
Invoking Methods
arrow(->) : 메소드 호출
dot : 핸들 상태 확인, 수정.
Handle(Geom_CartesianPoint) aCentre;
Standard_Real x, y, z;
if (aCentre.IsNull())
{
aCentre = new PGeom_CartesianPoint (0, 0, 0);
}
aCentre->Coord (x, y, z);
Handle(Standard_Transient) aPnt = new Geom_CartesianPoint (0., 0., 0.);
if (aPnt->DynamicType() == STANDARD_TYPE(Geom_CartesianPoint))
{
std::cout << "Type check OK\n";
}
else
{
std::cout << "Type check FAILED\n";
}
Null 핸들 접근 시 Standard_NullObject 예외 발생.
Invoking Class Methods
Standard_Integer aDegree = Geom_BezierCurve::MaxDegree();
Handle deallocation
reference counter 설명.
Cycles
순환 참조 시 자동 소멸 안됨.
회피 방법:
- 양방향 링크인 경우, 한 방향은 그냥 C++ pointer를 써라
- 소멸해야 하면 handle 하나를 nullify 해라.
Memory Management
작은 메모리 배열은 클러스터로 그룹핑, 재활용하는 방식 사용됨.
Usage of Memory Manager
C 함수 Standard::Allocate(), Standard::Free(), Standard::Reallocate() 가 제공됨.
C++ new( ), delete( )가 위 함수로 재정의됨.
Standard_DefineAlloc.hxx 가 제공하는 매크로 DEFINE_STANDARD_ALLOC가 모든 OCCT class에 사용되었음.
OCCT class에서 상속된 클래스에도 적용됨.
How to configure the Memory Manager
환경변수로 설정
- MMGT_OPT:
- 0 (default) : C heap 직접 사용 (malloc(), free()). MMGT_CLEAR 제외 다른 옵션은 모두 무시됨.
- 1 : 아래 설명대로 최적화됨.
- 2, Intel ® TBB optimized memory manager
- MMGT_CLEAR:
- 1 (default) : 모든 block 0으로 클리어.
- 0 : 그대로 반환.
- MMGT_CELLSIZE: large pools of memory 에 할당된 최대 블럭들 크기. Default 200.
- MMGT_NBPAGES: small blocks in pages (operating-system dependent)를 위해 할당된 메모리 chunk 크기. Default 1000.
- MMGT_THRESHOLD: heap에 반환되지 않고 내부적으로 재활용되는 블럭들의 최대 크기. Default 40000.
- MMGT_MMAP: large memory blocks 할당 방식
- 1 (default) : OS memory mapping functions 로 할당.
- 0 : malloc()로 C heap 할당.
Optimization Techniques
MMGT_OPT==1이면,
| block 종류 | 크기 | 특성 |
| small-sized | ~ MMGT_CELLSIZE | 단독 할당되지 않고, large-pool의 일부로 할당됨. |
| mid-sized | MMGT_CELLSIZE ~ MMGT_THRESHOLD | Standard::Free()로 재활용됨. Standard::Purge() 로 heap에 반환 가능. |
| large-sized | MMGT_THRESHOLD ~ | memory-pool 포함. MMGT_MMAP 설정의 방식으로 할당. |
Benefits and drawbacks
장점 : 유사 크기의 많은 블록을 계속 할당/해제하는 애플리케이션의 경우 50%까지 성능 향상.
단점 : 프로그램 수행 중 재활용 메모리 해제 안됨. 상당한 메모리 소모 및 메모리 누수로 오인.
메모리를 많이 쓰는 동작 후, Standard::Purge( ) 호출 필요.
Exceptions
Introduction
계층구조
root class : Standard_Failure (Standard package)
Raising an Exception
"C++ like" Syntax
throw Standard_DomainError ("Cannot cope with this condition");
메시지는 optional.
try
{
OCC_CATCH_SIGNALS
// try block
}
catch (const Standard_DomainError& )
{
// handle Standard_DomainError exceptions here
}
Regular usage
<ErrorTypeName>_Raise_if(condition, "Error message");
condition 만족시에만 raise
#define No_Exception // remove all raises
Handling an Exception
try { } 열고 OCC_CATCH_SIGNALS 삽입하면, 시스템 signal들을 예외로 다룸.
void f(1)
{
try
{
OCC_CATCH_SIGNALS
// try block
}
catch (const Standard_Overflow& ) // first handler
{
// ...
}
catch (const Standard_NumericError& ) // second handler
{
// ...
}
}
root인 Standard_Failure의 catch를 메인 블럭에 배치하는 것을 권장.
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <iostream>
int main (int argc, char* argv[])
{
try
{
OCC_CATCH_SIGNALS
// main block
return 0;
}
catch (const Standard_Failure& theFailure)
{
std::cerr << "Error " + theFailure.DynamicType()->Name() << " [" << theFailure.GetMessageString() << "]\n";
}
return 1;
}
Catching signals
main() 함수 시작 부분에 OSD::SetSignal() 메소드로 핸들러 설치하고 try { } 에 OCC_CATCH_SIGNALS 삽입 필요.
Implementation on various platforms
OCC_CONVERT_SIGNALS
1. Windows : 정의되지 않음. normal C++ 예외가 모든 경우에 사용됨.
2. Linux : 정의됨. signal 발생 시, 가장 가까운 OCC_CATCH_SIGNALS 삽입 위치로 long jump 해서 C++ 예외 throw.
Plug-In Management
Distribution by Plug-Ins
global universal identifier (GUID)로 인식됨.
C++ Plug-In Implementation
Factory 메소드 포함.
package Plugin.
Load( )함수
1) 다음 리소스 파일을 읽어 가용한 plug-in들과 위치 정보를 얻음.
$CSF_PluginDefaults/Plugin
2) library 로드.
Linux : LD_LIBRARY_PATH
Windows : PATH
3) PLUGINFACTORY 함수 호출로 객체를 리턴.
C++ Client Plug-In Implementation
Handle(FADriver_PartStorer)::DownCast(PlugIn::Load (yourStandardGUID));
#include <Standard_Macro.hxx>
#include <Standard_GUID.hxx>
#include <Standard_Transient.hxx>
class FAFactory
{
public:
Standard_EXPORT static Handle(Standard_Transient) Factory (const Standard_GUID& theGUID);
};
#include <FAFactory.hxx>
#include <FADriver_PartRetriever.hxx>
#include <FADriver_PartStorer.hxx>
#include <FirstAppSchema.hxx>
#include <Standard_Failure.hxx>
#include <FACDM_Application.hxx>
#include <Plugin_Macro.hxx>
static Standard_GUID StorageDriver ("45b3c690-22f3-11d2-b09e-0000f8791463");
static Standard_GUID RetrievalDriver("45b3c69c-22f3-11d2-b09e-0000f8791463");
static Standard_GUID Schema ("45b3c6a2-22f3-11d2-b09e-0000f8791463");
//======================================================
// function : Factory
// purpose :
//======================================================
Handle(Standard_Transient) FAFactory::Factory (const Standard_GUID& theGUID)
{
if (theGUID == StorageDriver)
{
std::cout << "FAFactory : Create store driver\n";
static Handle(FADriver_PartStorer) sd = new FADriver_PartStorer();
return sd;
}
if (theGUID == RetrievalDriver)
{
std::cout << "FAFactory : Create retrieve driver\n";
static Handle(FADriver_PartRetriever) rd = new FADriver_PartRetriever();
return rd;
}
if (theGUID == Schema)
{
std::cout << "FAFactory : Create schema\n";
static Handle(FirstAppSchema) s = new FirstAppSchema();
return s;
}
throw Standard_Failure ("FAFactory: unknown GUID");
return Handle(Standard_Transient)();
}
// export plugin function "PLUGINFACTORY"
PLUGIN(FAFactory)