目 录CONTENT

文章目录
UF

OpenC++ 开发指南

WenzhouXv
2023-04-02 / 0 评论 / 1 点赞 / 101 阅读 / 0 字

本文档使用约定 Conventions Used in This Document

为了帮助区分不同类型的文本,本文档使用了一些排印约定。 斜体字可以表示下列任何一种:

  • 程序中使用的名称或值, 如 UgObject, 或者 expr
  • 语言关键字, 如 int 和 if else
  • 文件名, 如 iostream.h
  • 函数, 如 main ( ) 和 askRadius ( )

C++源代码介绍如下:

UgSession::initialize ( )
// Your Open C++ code here
UgSession::terminate ( )

介绍 Introduction

Open C++是一个面向对象的NX编程接口,允许通过C++类层次结构访问NX对象和功能。 使用这个类层次结构中的方法,你可以创建、读取和修改NX对象,也可以控制NX应用程序本身。

Open C++的一些好处是:

  • Open C++使用标准的C++语法,这通常会导致应用程序代码更加简洁和可读。
  • 开放C++对象是通过指向C++对象的指针而不是标记来引用的,这是一种更加自然和富有表现力的编程风格。
  • Open C++通过C++异常机制报告错误,这允许您在少数地方本地化错误处理,避免了必须显式地检查单个函数调用返回的错误代码。
  • Open C++是强类型的,这意味着在不合适的NX对象上调用函数的任何尝试都将被C++编译器捕获,而不会导致运行时错误。
  • Open C++利用C++封装的优势,让你更容易识别与特定NX对象类型相关的函数集。
  • Open C++提供了一个框架来定义使用标准C++继承的对象的新类,使你的派生类能够覆盖虚方法,允许用户定义NX操作,比如Update对于新对象的意义。
  • Open C++可以与传统的Open C函数调用结合使用,允许在Open C++中创建的对象在Open C中访问,反之亦然。
  • Open C++通过在每个创建方法中指定所属部分来提供上下文管理的NX对象创建。
  • Open C++统一了曲线和边的求值和查询,允许你编写没有特殊情况分支的线框曲线和实边代码。
  • Open C++提供了编辑对象的便利性,而不需要查询对象是原型还是事件。
  • 开放C++坐在打开的C库之上,提供了一个相对较薄的C++接口层之上的传统开放C .开放C++实际上包含两个库:openpp图书馆提供对NX的访问对象和功能,而vmathpp库包含一个矢量数学包提供通用的数学运算。
  • Open C++应用程序既可以写成内部应用程序,也可以写成外部应用程序。 内部应用程序是UNIX上的共享库或Windows NT上的动态链接库,可以在交互式NX会话中执行。 外部应用程序是在NX会话之外独立执行的可执行文件。
  • 每个Open C++类和方法的详细文档都是通过一组HTML页面提供的。

开放的C++类 Open C++ Classes

概述 Overview

Open C++类有五种类型:应用程序类、对象类、模板类、助手类和数学类。

Application Classes控制NX应用程序,包括UgSession、UgInfoWindow和UgException等类。
Object Classes类,如UgArc、UgFace和UgExpression,定义了可以应用于NX部件文件中的对象的操作。 代表NX部件的UgPart类也属于这个类别。
Template Classes在V18之前,这些类提供了独立于平台的标准模板库(Standard Template Library, STL)类版本,主要用于数组(UgArray)和字符串(UgString)。 在V18中,STL类std::vector和std::string分别替换和废弃了UgArray和UgString。 还有一个用于遍历Open C++对象的模板类。
Helper Classes用于定义在其他类中使用的临时对象。 例子包括ThruPoint和Evaluator。
Math Classes包括与NX对象类一起使用的通用数学对象。 数学类包括点、向量、矩阵和坐标系统。

通常,每个类都定义在一个单独的头文件中,其名称基于类名,例如,UgArc类是在ug_arc.hxx中定义的。 有时,头文件还会包含额外的类定义,比如在头文件中定义的主类所需要的嵌套类或helper类。

您可以自由地调用Open C++类中定义的任何公共方法,但不能调用任何私有方法。 受保护的方法仅在您创建的派生类中有用。

应用程序类 Application Classes

会话类 Session Class

UgSession类的主要目的之一是执行Open C初始化,这必须在调用任何其他Open C++方法之前完成。 初始化(和终止)可以通过调用静态方法UgSession::initialize()和UgSession::terminate()来完成:

UgSession::initalize();
// Your Open C++ code goes here
UgSession::terminate();

或者通过构造一个UgSession对象:

UgSession mySession ( true );
// Your Open C++ code goes here

关于构造UgSession对象,有两件事需要注意。 第一个是UgSession析构函数会自动终止Open C,这通常会在UgSession对象超出作用域时发生。 另一个重要的一点是,当你像这样构造UgSession对象时,Open C的初始化可以被抑制:

UgSession mySession;

如果你在构造UgSession对象时以这种方式禁止Open C初始化,析构函数将不会终止Open C。

通过UgSession初始化Open C在功能上与调用传统的Open C函数UF_initialize()相同。 在应用程序的开始,你通常会执行UgSession初始化或调用UF_initialize(),但不能同时执行。 从那时起,您就可以同时调用Open C++方法和传统的Open C函数(UF_例程)。

UgSession类也可以用来控制当前NX会话的状态和行为。 例如,UgSession方法可以改变工作部分,修改层状态,关闭所有部分。

对象类 Object Classes

开放的C++类,如UgArc、UgFace和UgExpression,定义了可以应用于NX部件文件中的对象的操作。 还有一个UgPart类,它代表NX部件本身。 大多数Open C++应用程序都可能涉及到对NX对象的操作。

有两种对象类:基类和叶类。 基类定义了相关对象类型所共有的操作,它们不定义create()方法。 叶类定义特定于一个对象类型的操作,大多数类定义一个create()方法。 基类表示相关的NX对象,而叶类表示特定的NX对象。

表示NX对象的类层次结构提供了一个健壮的NX功能分类,使用基类来定义相关对象类型的通用操作。 此外,在某些情况下,它利用多重继承为不相关的对象类型定义公共接口。

所有NX对象的顶级基类都被称为UgObject。 它定义了某些对所有NX对象都通用的方法。 在基类中定义的方法的一个例子是UgObject::askOwningPart(),它返回特定NX对象所在的部分。

其他派生自UgObject的基类,包括UgTypedObject和UgDisplayableObject。 (注意,Open C++中大多数基类的名称都以“Object”结尾。) UgTypedObject类提供了命名和删除NX对象的方法,而UgDisplayableObject类提供了诸如blank/unblank、更改颜色、图层等方法。

创建 Create

在Open C++类层次结构的叶子节点上,C++类代表了实际的NX对象类型,例如,UgArc代表了arc对象,而UgExpression代表了表达式对象。 这些类被称为可实例化类,因为你可以实际创建这些类型的C++对象,每个对象都对应于驻留在部件文件中的NX对象。 要创建NX对象,需要调用相应类的静态create()方法,如下所示。

UgPart *pWorkPart = UgSession::getWorkPart ( );
UgExpression *pExpr;
pExpr = UgExpression::create ( "diameter", 4.25 , pWorkPart );
double diaValue = pExpr->evaluate ( );

NX对象总是通过指针引用(例如,在上面的例子中,pExpr),而不是显式地构造该类的C++对象。 事实上,C++的构造函数是NX对象类的受保护成员,所以你不能无意中创建一个。 通过指针访问NX对象可以节省内存使用,并确保C++代码始终与NX模型的状态保持同步。

UgAssemblyNode类是叶子类有create()方法这一规则的一个例外。 UgAssemblyNode类的一个对象是通过调用UgPart::addPart()方法创建的:

UgPart           *pWorkPart = UgSession::getWorkPart ( );
UgAssemblyNode *pNode;
pNode = pWorkPart->addPart ( "component.prt", "", "",
                       CoordSys ( ), -1 );

有些类重载了静态create()方法,为您提供创建NX对象的替代方法。 下面的例子演示了创建表达式的三种不同方法。

UgPart           *pWorkPart = UgSession::getWorkPart ( );
UgExpression     *pExpr1, *pExpr2, *pExpr3;
std::string          strName ( "diameter1" );
pExpr1 = UgExpression::create ( "radius", 4.25, pWorkPart );
pExpr2 = UgExpression::create ( "diameter=2*radius", pExpr1 );
pExpr3 = UgExpression::create ( strName, "2*radius" );

所有create方法的最后一个参数是一个可选参数,它指定了部件上下文,即“拥有”新创建对象的部件。 默认的部分上下文是工作部分,所以如果您调用一个创建方法而没有提供最后一个参数,您的新对象将属于工作部分。 但是,如果您希望创建的新对象由可能不是当前工作部件的部件拥有,则应该将部件上下文作为最后一个参数。 部件上下文可以是指向目标部件已经拥有的其他对象的指针,也可以是指向部件对象的指针。 例如:

UgPart         *pOtherPart;
// Initialize pOtherPart to point to a valid UgPart object
UgExpression    *pExprNew;
pExprNew = UgExpression::create("length=3.0", pOtherPart);

读/写访问 Read/Write Access

一旦你有一个指向NX对象的指针,你就可以用它来调用在这个类或它的基类中定义的任何方法。 假设pArc是一个指向UgArc的指针,你可以调用pArc上的各种方法来查询或修改NX arc对象,如下例所示。

pArc->setRadius ( 2.5 );
double len = pArc->computeArcLength ( );
int layer = pArc->getLayer ( );

虽然UgArc对象可以调用这三个方法,但只有setRadius()在UgArc类中定义。 其他两个方法继承自基类:UgEvaluatableObject::computeArcLength()被所有曲线对象继承,UgDisplayableObject::getLayer()被所有可显示的NX对象继承。

转换 到 /从 标签 Converting to/from Tags

可以将Open C++代码与传统的Open C代码结合起来,并来回传递结果。 要做到这一点,你需要使用UgObject::find()和UgObject::getTag()来转换Open C++指针到/从标签。 UgObject::find()返回一个指向UgObject对象的指针,因此为了有用,应该使用dynamic_cast将返回的指针转换为一个更合适的指针。 (请参阅动态铸造部分。) 例如,

int       color;
tag_t     tag1, tag2;
 
// Call the traditional Open C function to select a line.
// Note: this returns the tag of the selected line as `tag1'
UF_UI_select_single ( ..., &tag1, ... );
 
// Use the `find' method to get the pointer of the NX
// object corresponding to `tag1'
UgObject     *pObj = UgObject::find ( tag1 );
if ( pObj )
{
    UgLine *pLine = dynamic_cast <UgLine *> pObj;
    if ( pLine )
    {
 
        // Invoke a Open C++ method using that pointer
        pLine->setColor ( Red );
 
        // Now convert the pointer back to a tag (`tag2').
        // Note that `tag1' and `tag2' should be identical.
        tag2 = pLine->getTag ( );
 
        // Call a traditional Open C function to get the color
        // using `tag2' � it should be Red.
        UF_OBJ_ask_color ( tag2 , &color );
    }
}

上面的例子说明了关于UgObject::find()的一点,如果不能为特定的对象找到create函数,该方法可能返回0。 通常,在使用UgObject::find()和dynamic_cast返回的指针之前,最好检查一下它们是否有效。

文件 Parts

类UgPart包含了可以应用到整个NX部件的方法。 例如,它包含创建新部件、打开现有部件、保存和关闭的方法。 注意,关闭一个单独的部分是UgPart类的一个方法,而关闭所有部分是UgSession类的一个方法。 UgPart还包含了访问和修改部件属性和其他存储在部件文件中的数据的方法。

UgPart *pPart = UgPart::open( "valve.prt" );
// Find out what the part units are
bool isItMetric = pPart->isMillimeters ( );

UgObject::find()和UgObject::getTag()方法可以用来转换UgPart指针到/从部分标签,以兼容传统的Open C函数。

如果需要遍历部件中的所有对象,而不管类是什么,可以使用UgPart::iterateFirst()和UgPart::iterateNext()方法。 迭代是通过调用UgPart::iterateFirst()来启动的,它返回一个指向该部分中找到的第一个类型化对象的指针。 在对UgPart::iterateNext()的后续调用中,找到的前一个对象作为参数传递。 迭代以这种方式继续,直到UgPart::iterateNext()返回0,表示已经找到所有对象。

UgPart           *pWorkPart = UgSession::getWorkPart();
UgTypedObject    *pCurObj;
 
for ( pCurObj = pWorkPart->iterateFirst ( );
      pCurObj;
      pCurObj = pWorkPart->iterateNext ( pCurObj ) )
{
    std::string name = pCurObj->getName ( );
}

注意,因为这两个迭代方法可以找到所有类型的NX对象,所以它必须返回一个指向基类Open C++的指针,这个指针适用于所有类型的NX对象,也就是一个指向UgTypedObject对象的指针。 因此,您只能在这个指针上调用为所有类型化NX对象定义的方法,例如访问名称和属性。 如果您想在这个指针上调用特定于对象的方法,请参阅本文档后面的动态转换一节。

关于使用模板类UgIterator的另一种迭代方法,请参见下面的模板类部分

原型和事件 Prototypes and Occurrences

术语原型和出现指的是如何在程序集上下文中访问和操作NX对象。 原型是组件部件中的实际几何对象,而事件则是面向组件中的原型几何对象的对象。 当你使用Open C++遍历NX对象时,可以同时找到原型和事件。 如果您有一个原型对象,您可以读取和修改它的定义几何表示。 然而,如果你有一个发生对象,你只被允许读取它的定义几何表示; 你不能编辑它。 编辑对象的最简单的方法,无论您是否有一个发生或原型,如下所示。

UgLine     *pLine;
// Initialize the pLine pointer
Point3      newPt;
. . .
// Set the end point of the line to (0.0, 0.0, 0.0)
( pLine->askPrototype ( ) )->setEndPoint ( newPt );

请注意,UgLine::askPrototype()将返回适当的原型,如果pLine出现,或者它将返回pLine本身,如果pLine已经是一个原型。

要检查对象是原型还是事件,可以执行以下操作。

UgLine    pLine;
// Initialize the pLine pointer
. . .
if ( pLine->isOccurrence ( ) )
{
    // it�s an occurrence
}
else
{
    // it�s a prototype
}

曲线和边缘 Curves and Edges

NX对于线框曲线(独立线、弧和样条)和边缘曲线有不同的对象,这些对象出现在实体和板材上。 然而,NX类的层次结构允许你编写通用代码,同样适用于线框曲线或边缘。 因为所有的线框曲线和边都继承自UgEvaluatableObject基类,所以你可以用完全相同的方式计算它们。 例如,这允许您编写如下代码来计算一个对象的弧长并将其与另一个对象相交,而无需编写特殊情况代码来检查对象类型。

UgEvaluatableObject     *pObj1, *pObj2;
// Assume the user selected pObj1 and pObj2 so you don't know
// their types (i.e. the user might have selected an edge
// and a wireframe curve)
 
// Get the arc length of each object, regardless of type
double len1 = pObj1->computeArcLength ( );
double len2 = pObj2->computeArcLength ( );
 
// Compute the intersection points for these two objects
std::vector<CurveCurveIntersectionPoint> iPts;
iPts = pObj1->computeIntersectionPoints ( pObj2 );

也可以通过UgEvaluatableObject::askEvaluator()返回的Evaluator对象访问边缘和线框曲线上不同位置的点坐标和法线。

上述方法是通用的,因为它们适用于任何类型的UgEvaluatableObject对象,无论它是一条线,弧,线性边,圆形边,等等。 但在某些情况下,你可能需要访问更具体的信息,比如对象的半径,而你不知道该对象是线框弧对象还是圆形实边。 您可以这样做,而无需查询对象是否为边,如下面的示例所示。

UgEvaluatableObject *pCircularObj;
// Initialize pCircularObj to some circular object,
// but not know whether it is a wireframe arc or
// a circular solid edge.
 
// Get the generic curve object for it.  The dynamic cast
// should work since we know we have an arc or circular edge.
Arc *pArc = dynamic_cast < Arc * > pCircularObj->askCurve ( );
 
// Now we can do specific inquiries on it
double radius = pArc->getRadius ( );

这种通用性不会给更具体的情况带来开销。 如果您知道您正在操作一个UgArc对象,那么您就可以访问曲线数据,而无需先通过curve对象。 这是可能的,因为UgArc类是由UgCurveObject和Arc类派生的。 例如:

UgArc *pUgArc;
// Initialize pUgArc to a wireframe arc �
// not a circular solid edge.
 
// We can immediately do arc specific inquiries on it
double radius = pUgArc->getRadius ( );

模板类 Template Classes

在V18之前,Open C++包含了用于字符串(UgString)和动态数组(UgArray)的模板类。 它们都被用作各种Open C++方法的输入和输出。 这些类与C++标准模板库(STL)中的std::string和std::vector类非常相似。 在V18中,STL类std::vector和std::string分别替换和废弃了UgArray和UgString。

建议针对V18库编写的新代码直接使用STL类。 头文件ug_vector。 hxx ug_string。 hxx作为独立于平台的方法提供,用来包含分别定义std::vector和std::string的STL头文件。

当前使用UgArray或UgString的旧代码必须修改以使用V18库编译、链接和运行。 我们提供以下步骤:

  1. 头文件ug_array。 hxx在V18中不再存在; 现有代码中这个头文件的每个实例都应该替换为ug_vector.hxx。 (头文件ug_string。 hxx在V18中仍然存在。)
  2. 类UgArray和UgString不再存在于V18; UgArray的每个实例都可以被替换为std::vector, UgString的每个实例都可以被替换为std:string。 或者,如果不能更改代码,可以提供UgArray和UgString的新定义。 应使用下列定义:
     typedef  UgString  std::string;
     #define  UgArray   std::vector

UgPart      *pMyPart;
// Initialize the pMyPart pointer
 
// Get the description string for this part
std::string     description=pMyPart->getDescription ( );
 
// Make sure it isn't a null string
if (!description.empty ( ))
{
    // do something with it
}

你也可以从std::string对象中获得一个指向字符数组的C风格指针,以便与C函数兼容。 如果description仍然是上面例子中的std::string对象,那么:

printf( "Description = %s/n", description.c_str() );

重要的是要记住,来自std::string对象的c风格指针必须被视为const指针; 你不应该通过c风格的指针修改字符串。

迭代模板类 Iteration Template Class

你通常会使用UgIterator类来循环遍历给定类的所有NX对象。

// Construct an iterator for NX face objects
UgIterator < UgFace *> curFace;
// Loop through all faces
while ( !curFace->isFinished ( ) )
{
    // Get the name of the current face
    std::string faceName = (*curFace)->getName ( );
    curFace->findNext ( );
}

请注意,迭代给定类型的所有对象有三个步骤:

  1. 构造一个UgIterator对象。 UgIterator是一个模板类,这意味着它是一个泛型类,可以用于迭代许多不同类型的NX类。 当你构造UgIterator对象时,你可以识别特定的NX类,如上面的< UgFace * >。 类必须是可实例化的。 事实上,如果你试图在UgConicObject这样的基类上构造UgIterator对象,你会得到一个编译错误。 UgIterator构造函数也有一个可选参数(在上面的例子中没有使用),它允许你迭代当前工作部分以外的部分中的对象。
  2. 遍历所有需要的对象,一次一个。 当UgIterator对象从UgFace *>::isFinished()方法返回true时,while循环终止。
  3. 在while循环中,使用UgIterator对象上的*操作符获取当前NX对象的指针。 在上面的例子中,(*curFace)返回一个指向UgFace对象的指针。

类似地,你可以使用UgIterator类来查找当前会话中加载的所有NX部件。

// Construct an iterator for NX part objects
UgIterator < UgPart *> curPart;
// Loop through all loaded parts
while (!curPart->isFinished ( ))
{
    // Close this part if it is not metric
    if ( !(*curPart)->isMillimeters ( ) )
    {
        (*curPart)->close ( true );
    }
    curPart->findNext ( );
}

助手类 Helper Classes

Open C++包含了许多帮助类,它们需要将数据传递到其他类上定义的方法中。 例如,ThruPoint对象用于指定UgSpline曲线上点的位置、斜率和曲率。

UgSpline             *pSpline;
// Initialize pSpline pointer
 
std::vector < ThruPoint > thruPts; // Array of ThruPoint objects
std::vector < double    > params; // Array of doubles
bool                  periodic;
int                   order;
 
// Get defining data for a spline
pSpline->getThruPoints ( &periodic, &order, &thruPts, &param );

请注意,helper类没有使用“UG”前缀命名

数学类 Math Classes

vmathpp库包含用于通用数学操作的类,特别是用于点、向量和矩阵的类。 当调用NX对象的各种方法时,需要这些类的对象。 这些类中重载了许多标准数学操作符,这通常会导致代码更简洁、更易读。

Point3   pt1 ( 0, 2, 4 );
Vector3  offset ( 1, 2, 3 );
Point3   pt2 = pt1 + offset;
UgLine  *pLine = UgLine::create ( pt1, pt2 );

vmathpp库的另一个特性是,它包含的类完全独立于NX。 你可以在NX之外的其他应用程序中使用这个库及其类。

一个开放的C++示例应用程序 A Open C++ Sample Application

Open C++发行版CD包含一个名为ufx_cycle的示例应用程序,它可以用作Open C++编程的介绍。 这个示例应用程序演示了如何使用Open C++:

  • 打开一个零件文件
  • 访问部件的信息,包括归档历史、属性和状态
  • 循环遍历部件中的所有对象
  • 访问对象的基本信息,如类型、层等

高级的主题 Advanced Topics

异常 Exceptions

每当错误发生时,Open C++方法都会抛出异常,这使您不必检查每个被调用方法返回的错误代码。 您可以使用try块和catch块来管理这些异常,这些块使您能够在异常发生时恢复、恢复或重新抛出异常。

每当发生数学错误时,矢量数学包(vmathpp)抛出一个从VectorMathException派生的异常对象。 例如,构造Matrix3对象可以导致抛出VectorMathZeroVector或vectormathnon正交异常对象。 你可以将vmathpp错误与抛出的异常对象的类匹配:

Vector3    x_vector, y_vector;
// Initialize x_vector and y_vector
try
{
    Matrix3 matrix3 ( Matrix3::XY_Input, x_vector3, y_vector3 );
}
catch ( VectorMathZeroVector & )
{
    cout << "Un-initialized or zero vector" << endl;
}
catch ( VectorMathNonOrthogonal & )
{
    cout << "Vectors are non orthogonal" << endl;
}
catch ( VectorMathException & )
{
    cout << "Caught an unexpected vmathpp exception" << endl;
}

每当发生错误时,Open C++主库(openpp)抛出一个UgException对象。 例如,尝试添加一个已经存在的属性会导致抛出一个UgException对象。 你可以匹配openpp错误类的异常对象抛出:

std::string    title ( "AttributeName" );
int         int_value = 0;
 
try
{
    typed_object->addIntAttribute ( title, int_value );
}
 
catch ( UgException &exception )
{
    // Check the error code of the exception against a known
    // error code defined in uf_modl_error.h
    if (ATTRIBUTE_ALREADY_EXISTS == exception.getErrorCode ( ) )
    {
        cout << "Attribute already exists" << endl;
    }
    else
    {
        cout << "Caught unexpected NX error:" << endl;
        cout << exception.getErrorText ( ) << endl;
    }
}
 
catch ( VectorMathException & )
{
    cout << "Caught an unexpected vmath exception" << endl;
}

注意,NX根本不会捕获任何C++异常。 客户机有责任捕获并正确处理所有异常。 将来,NX可能能够捕获Open C++异常。 最低限度,你应该用最后的机会try and catch块包装所有Open C++应用程序。

您可以决定什么粒度的错误检查最适合您的情况。 你可以像上面的例子一样用try和catch块包装单独的Open C++调用,或者你可以在你的应用程序中相当高的层次上捕获错误。 通常,您将结合使用这两种技术。

卸载共享库 Unloading Your Shared Library

你不应该在Open C++应用程序中使用ufusr_ask_unload()函数,因为Open C++用Open C记录回调来管理标签和UDOs。 使用此函数可能导致不可预知的结果。

Open C++对象的内存管理 Memory Management of Open C++ Objects

通过引用和通过值语义 By Reference versus By Value Semantics

一个表示NX部件文件中的对象的Open C++对象总是“引用”返回,也就是说,通过一个指向对象的指针,比如一个指向UgLine对象的指针。 所有其他对象都是“按值”返回的,除非需要使用dynamic_cast操作符。 例如,一个Curve对象是通过一个指针返回的,这样您就可以对它调用dynamic_cast,以便将它转换为一个Line对象的指针。

对象的通信 Object Correspondence

对于一个给定的NX对象,Open C++对象是存在的,但直到Open C++需要它时才存在。 通常,当NX对象的指针通过create或inquire方法返回时,Open C++对象就会绑定到NX对象上。 如果一个Open C++对象存在,那么它对于一个特定的NX对象来说是唯一的。 也就是说,对于任何给定的NX对象,最多只能有一个Open C++对象。

删除 Delete

Open C++按引用管理对象,而按值管理对象则在超出作用域时被删除。 永远不要在按引用对象上调用delete操作符。 如果你想删除NX对象,你应该调用UgInPartObject::destroy()代替。 此方法将从部件文件中删除该对象,因此用户或应用程序不再可以访问该对象。 但是,它不会立即删除相应的Open C++对象。 相反,它将其设置为“空状态”。 类似地,如果用户交互式地删除一个NX对象,相应的Open C++对象(如果有的话)将被设置为空状态。 当对应的NX对象被删除时,Open C++对象不会被删除,因为NX对象可能会通过撤销“恢复”。

实际上,只有当对应的NX对象无法恢复时,Open C++对象才会被删除。 例如,关闭该部分将删除与该部分关联的所有Open C++对象。

即使你的Open C++对象的指针在删除它的NX对象后仍然有效,你也不能用它做很多事情。 如果您试图对它进行任何查询,就会生成一个异常。

UgLine *pLine;
// Initialize the pLine pointer
 
// The following method will remove the line from the part file
// but pLine is still a valid pointer.
pLine->destroy ( );
 
// Although the pLine pointer is still valid, it refers to an
// object that is in the "null state" so the following line
// will cause an exception to be thrown
std::string name = pLine->getName ( );

撤销 UNDO

一个处于空状态的Open C++对象可以被重新关联到它原来的NX对象。 当您撤消到删除NX对象之前的状态时,就会发生这种情况。 (这是在NX对象被删除时保留Open C++对象的主要原因。 否则,您就会丢失引用,在撤销之后就没有办法取回它了)。

Open C++扩展对象中的持久化数据会受到撤销的影响。 对于任何可能成为Open C++扩展对象一部分的瞬态数据,没有任何机制。 注意,我们不建议再使用UgExtensionObject了——通用API(在NX5中)对UDO有更好的解决方案。

一般的规则是,如果一个Open C++对象可以通过撤销恢复,那么它将永远不会被删除。 但是,如果撤销到创建Open C++对象之前的状态,或者在删除Open C++对象之前没有可达到的撤销标记,那么Open C++对象将被删除。

Dynamic Casting

向上投射总是安全的,但向下投射则不然。

UgLine         *pLine;
UgTypedObject  *pTyped;
 
// If pLine is a valid pointer, the following upcast works
// No explicit upcasting is required in C++
pTyped = pLine;
 
// The following downcast is unsafe, even if pTyped is a
// valid pointer because it may not be a pointer to a UgLine
// object.
pLine = (UgLine *) pTyped;

当进行向下转换时,你应该使用C++的dynamic_cast操作符。 如果可以执行向下转换,这个函数返回一个指向所需对象的指针; 否则,返回0。 通过这种方式,您可以将类层次结构中的一系列类向下移动。 例如,你可以通过以下方式确定一个UgEvaluatableObject对象是否是线性的:

Curve *pCurve = pEvalObj->askCurve ( );
 
if ( dynamic_cast < Line * > ( pCurve ) )
{
    cout << "A linear evaluatable object" << endl;
}
else
{
    cout << "A non linear evaluatable object" << endl;
}

向下转换在迭代UgTypedObject对象时也很有用。

UgPart           *pWorkPart = UgSession::getWorkPart();
UgTypedObject    *pCurObj;
 
for ( pCurObj = pWorkPart->iterateFirst ( );
      pCurObj;
      pCurObj = pWorkPart->iterateNext ( pCurObj ) )
{
    UgArc *pUgArc = dynamic_cast <UgArc *> pCurObj;
    if ( pUgArc )
    {
        double radius = pUgArc->getRadius ( );
    }
    else
    {
        cout << "This is not an arc" << endl;
    }
}

许可 Licensing

Open C++应用程序与传统的Open C应用程序共享相同的许可证。 如果您的应用程序同时使用Open C++和传统的Open C函数,那么它将检查一个单一的许可证。 当Open C以以下任何一种方式初始化时,许可证被检出:

  • 在构造函数中创建一个指定为true的UgSession对象

  • 调用UgSession::initialize()静态方法

  • 调用UF_initialize()函数 当Open C被终止时,许可证通常被签回,这可以通过以下方式发生:

  • 在构造函数中指定true创建的UgSession对象超出了作用域

  • 调用UgSession::terminate()静态方法

  • 调用UF_terminate()函数

重要的是要注意,一旦外部Open C应用程序签入了许可证,它就不能再签出了。

开放C++设计背景 Open C++ Design Background

下面提供了一个高层次的概述,并解释了Open C++的许多设计决策背后的基本原理。 对编码标准进行了总结。

头文件 Header Files

Open C++头文件被设计成尽可能多地隐藏实现细节。 这有助于确保客户端根据类所做的事情而不是它如何做来设计程序。 例如,您应该忽略类的私有部分及其友元,以及宏和模板的实现细节。 您可以引用类的受保护部分,但只能在派生类中。 公共部分是类中供所有人使用的部分。 不要修改宏或模板。

通常,每个头文件声明一个类及其辅助类。 这个类用于命名头文件。 例如,UgLine在ug_line中声明。 而UgSpline和它的助手类ThruPoint是在ug_spline.hxx中声明的。

命名约定 Naming Conventions

Open C++头文件扩展了hxx。 以“ug_”开头的头文件包含NX对象和概念的定义,而那些不建模通用对象/概念的头文件。 例如,ug_line。 hxx模型的Open C线而线。 HXX模拟了一条数学线。

嵌套 Nesting

Open C++头文件的嵌套被保持在最低限度,以限制编译时的依赖关系。 例如,在ug_line中,Point3被声明为一个不完整的类。 而不是包含point3.hxx。 这意味着客户端必须包含ug_line。 hxx point3。 hxx,以便调用UgLine::getStartPoint()。

类集 Classes

命名约定 Naming Conventions

以“Ug”开头的Open C++类表示NX对象和概念,而那些不表示通用对象和概念的类。 例如,UgLine表示NX线,line表示数学线。 以“Object”结尾的类是基类,可实例化的“Ug”类就是从基类派生出来的。 例如,“Ug”的可实例化类UgLine继承自基类UgCurveObject。

嵌套 Nesting

为了简化设计,Open C++类通常不会嵌套在其他类中。 例如ug_face.hxx, Loop是在UgFace外部声明的,即使它是一个UgFace助手类。

模板类 Template Classes

在V18之前,Open C++中有三个模板类。 UgArray和UgString分别是STL类std::vector和std::string的部分包装器。 UgIterator是第三个模板类。 UgIterator可以用于迭代部件文件中的对象,也可以用于迭代当前会话中所有打开的部件。 在V18中,STL类std::vector和std::string分别替换和废弃了UgArray和UgString。 UgIterator在V18中仍然存在。 不要依赖于模板类的实现,也不要修改模板。

动态与静态行为 Dynamic versus Static Behavior

根据定义,C++对象是静态定义的。 因此,任何不受直接用户控制的动态行为都不会被建模为一个“Ug”类。 例如,在Open C++中没有UgLinearEdge类。 这是因为边可以改变形状作为一个编辑操作的副作用,结果是一个UgLinearEdge对象可能不再是线性的编辑后。 由于这个原因,只有UgEdge对象被建模。

这些动态行为是通过方法和助手类建模的。 例如,你可以通过调用UgEvaluatableObject::askCurve()来获取一条边的曲线数据,并从返回的curve对象中确定这条边是否是线性的。 重要的是要记住,Curve对象返回的只是UgEdge对象在某个时间点的快照; 如果UgEdge对象随着模型更新而改变形式,那么这种改变不会反映在任何在改变之前获得的Curve对象中。

多重继承 Multiple Inheritance

多重继承用于“混合”功能,不局限于类层次结构的单个分支。 例如,所有类型化对象都是可归属的(也就是说,可以包含属性),但不是所有可归属的对象都是可归属的。 因此,UgTypedObject和UgPart都必须‘mixin’UgAttributableObject。 多重继承保证了属性接口在整个类层次结构中保持一致。 只在绝对必要的情况下使用多重继承。

多重继承被广泛用于统一曲线和边的访问。

方法 Methods

每个类通过方法发布其接口。 下面解释了如何在Open C++中定义方法。

命名约定 Naming Conventions

返回以"is"开头的布尔值的方法。 例如,

bool is_solid = body->isSolid ( );

返回数据的方法以“ask”或“get”开头。 例如,

int             type = typed_object->askType ( );
const std::string  name = typed_object->getName ( );

以“set”开始编辑数据的方法。 “get”方法有一个对应的“set”方法,而“ask”方法没有。 例如,你不能“设置”一个对象的类型,但你可以“设置”它的名称:

typed_object->setName ( "Hello world" );

签名 Signatures

返回单个结果的方法是通过返回值来实现的。 如果一个对象由这样的方法返回,它要么作为const对象返回,要么作为对象的指针返回。 返回多个结果的方法是通过输出参数来实现的,输出参数作为方法的指针传递。

输入参数要么按值传递,要么作为const引用,要么作为指向“Ug”类对象的指针传递。 输入参数总是列在输出参数之前。

默认参数 Default Parameters

默认参数仅用于方便客户端代码; 它们不是用来改变方法的语义的。 例如,UgEvaluatableObject::computeIntersectionPoints()中的公差参数默认为标准公差,这对于大多数应用程序来说是足够的。

重载 Overloading

重载有时用于提供具有相同名称但具有不同语义的多个方法。 例如,有三个UgExpression::create()方法。 所有三个创建一个UgExpression对象,虽然每一个以不同的方式:一个从完整表达式创建一个UgExpression std:: string对象,另一个从左手边(lh) std:: string对象和一个右手边(RHS) std:: string对象,第三从lh std:: string对象和皇家双重价值。

操作符重载 Operator Overloading

运算符重载仅在存在明确数学解释的情况下使用。 否则,就使用方法。 这就是为什么vmathpp类比openpp类更多地使用操作符重载。

虚拟方法 Virtual Methods

很少有Open C++方法是虚的,因为它们不能被重写。 您不应该试图通过实现自己的版本来隐藏任何Open C++方法。

大多数Open C++虚拟方法都不会被用户编写的代码所覆盖。 例如,UgExpression和UgTypedObject重写了虚拟的UgInPartObject::destroy()方法,因为它们都需要自己的实现。 虚方法通常用于保证接口在整个类层次结构中保持一致。

唯一可以覆盖的Open C++虚拟方法是UgExtensionObject方法infoObject()、memberDeletion()和update()。 这些方法的实现应该由派生类提供。 注意,我们不建议再使用UgExtensionObject了——通用API(在NX5中)对UDO有更好的解决方案。

静态方法 Static Methods

当不需要this指针时,方法被声明为静态的。 例如,你可以在没有UgInfoWindow对象的情况下写入信息窗口:

UgInfoWindow::write ( "Hello world" );

不需要this指针,因为只有一个信息窗口。

所有的create()方法都是静态的,因为对象还不存在。 例如,你使用静态UgPoint::create()方法来创建一个NX点对象。

// Create a point at the origin and return its pointer
UgPoint *pUgPoint = UgPoint::create ( Point3 ( ) );

构建开放C++应用程序 Building Open C++ Applications

本节讨论了构建和执行Open C++应用程序所涉及的各种系统问题。

平台 Platforms

开放C++应用程序只支持以下平台:

平台
惠普(HP)
硅谷图形(SGI)
Sun
网络窗口

开放C开发工具 Open C Development Tools

基本的Open C开发工具(如ufcomp、uflink、ufmenu和Microsoft Visual C++)成功地编译和链接了Open C++应用程序。 下面介绍了编译和链接Open C++应用程序的指导原则

  • .c, .cc, .cpp或.cxx的扩展名可以与ufcomp编译引擎或ufmenu一起使用。 如果选择使用提供的Open C开发工具以外的工具,则需要在使用的工具中复制这些工具中使用的编译开关。
  • 与基本的Open C API应用程序不同,包含Open C++功能的库没有链接到NX中。 因此,当一个内部或外部的Open C++应用程序被链接时,库的位置以及库名必须在链接行中指定。
  • 在UNIX系统上,你应该把它指定为: L $ {UGII_BASE_DIR} / ugii uglibs lopenpp lvmathpp。
  • 如果您使用的位置不是上面显示的位置,您将不得不调整LD_LIBRARY_PATH或SHLIB_PATH变量,以成功运行Open C++应用程序。
  • 在Windows/NT系统上,您应该将以下导入库添加到uflink。 mak文件: libopenpp。 自由libvmathpp.lib
  • 基本的Open C编译工具会自动在正确的目录中查找Open C++应用程序所需的头文件。
  • 如果你有一个与Open C++头文件名称相匹配的头文件,你可能会在文件名上遇到冲突。 然而,由于Open C++头文件使用.hxx扩展名,这种情况不太可能发生。
  • 由于Open C++在其接口中使用模板,因此在编译和链接时需要小心。 许多供应商编译器创建一个中间目录来存储对象文件或其他文件,为链接器提供扩展模板方面的指导。 存储这些文件的目录必须在编译和链接时都可用。

Visual C++开发指南 Visual C++ Development Guidelines

  • Visual C++开发指南 libopenpp.lib libvmathpp.lib Open C AppWizard将自动添加这些库。
  • 为了方便起见,上面引用的导入库位于Open C目录中,它们引用的dll位于所有NX dll的标准位置,因此您不需要更改您的PATH变量。

术语 Terminology

Base class不能实例化的类。 它用于收集与所有派生类相关的方法和成员数据。
Dynamic cast一种C++操作,其中指向基类的指针向下转换为指向派生类的指针。
Exceptions用于报告和从运行时错误中恢复的C++机制。
Instantiable class可以为其创建对象的类。
PropertyNX对象关联的数据,该对象派生自一个标准的Open C++对象。
Prototype一个NX对象,它在组件部件文件中表示一个几何对象。
Occurrence一个NX对象,它表示在程序集中几何对象是如何定向的。 此事件将对组件部件中的原型对象应用转换,以在组件中正确定位和定向该对象。
Static method在类中定义的方法,但可以在不构造该类对象的情况下调用该方法。
Open C也被称为“传统的Open C”,这是一组C可调用函数,提供对NX对象和功能的访问。
Open C++一组C++类,包含访问NX对象和功能的方法。
User Defined Object一个NX对象,它的数据和行为是通过用户编写的应用程序定义的。

本万维网服务器上的所有文件及相关图形均受版权保护。 UGS是一个平等的机会雇主,m/f/v/d。 NX、Unigraphics、Parasolid和GRIP是UGS的注册商标。 UGS版权所有 所有其他商标或注册商标属于各自的持有人。 其中的信息可在不另行通知的情况下更改,且不代表UGS方面的承诺。

1
uf
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区