日常折腾日记:手动配置UG二次开发环境——使用NX Open C++和Visual Studio ———————————————— 版权声明:本文为CSDN博主「wanghy1995」的原创文章,遵

ug 专栏收录该内容
2 篇文章 0 订阅

一、背景
最近需要做一些CAD软件二次开发的工作,所以这两天花了些时间了来入门。之前几乎没用过这个软件,以前用过Pro/E,但是的它界面实在是太难看了,这促使我有了学习UG的动力。折腾数日,这几天的收获主要是了解了一些UG开发的基本的概念,和有了初步的二次开发思路。本文并没有太高级的内容,只是记录了本人的这两天的经历和学习思路。

本人使用了UG12.0,VS2019,在64位的WIN10系统上。

关于UG软件的介绍网上很多,这里只说一下UG提供的一些编程开发接口,这一块搞清楚很有必要,否则看文档会晕的。这里是官方文档。
UG提供了很多种开发接口,包括NX Open、GRIP、SNAP、KF等。其他几个都比较小众,最强大也好用的就是NX Open系列。这个系列里面大概分三类,它们可以相互兼容,可以同时使用。

Open C:原来的名字叫UF(User Function),处于NX Open系列的最底层,使用C语言,国内很多比较早的书和教程都用这个,但是由于它是C语言,很多东西都比较原始,开发难度比较大。
Open C++:基于Open C做了封装,使用C++语言。结合了C++面向对象的优势,相较之下好用一些,但同时失去了少量的功能性,经常与Open C同时使用。
NX Open:基于Open C,提供了多种语言可供选择(C++、JAVA、Python、.NET等等)。相较前两个更加完善。本人选择了这个系列的NX Open C++(JAVA和Python可能会更方便些,可惜资料不多)。
官方手册里给的结构图:

还有一个要搞清楚的概念是,UG支持两种形式的二次开发程序,分别是内部模式和外部模式(这个概念在Pro/E二次开发里面叫做异步模式和同步模式)。内部模式就是指以动态链接库的形式嵌入到UG的主程序里使用,我们做二次开发的输出文件是*.dll形式的动态链接库,这种文件不能直接运行,必须嵌入到其他程序中使用。外部模式的程序可以独立地运行,通过调用UG的库来实现功能,这种输出文件是*.exe形式的可执行文件。本人使用的是外部模式,内部模式开发也类似,配置稍有不同。二者的功能可以完全一样,不同的地方在于程序入口,。

二、UG安装目录结构
网上的资料对这方面的描述,都是直接使用了UG专门为VS提供的项目模板,这个方法也是官方手册上提供的唯一方案,可能是考虑客户的方便吧。但是它对UG和VS版本有要求,对于有强迫症的我来说,重新让我装一个低版本的VS并不是个好的解决方案。网上有的教程说UG只能用对应版本,其实不是的,只是项目模版对VS版本有要求,折腾一下把环境搭好了代码一样写的。
先看一下UG的目录结构:
我的机子上安装目录是:C:\Program Files\Siemens\NX 12.0
里面是这样的:(可能会少些文件夹,我只装了建模部分和二次开发接口部分,大概5个G,全装的话应该要20G)

其中

NXBIN:是UG主程序文件夹,UG主要的可执行程序都在这里;
UGOPEN:是UG二次开发编程接口所在的目录,里面是Open C的库(libxxx.lib,.dll)和头文件(主要形式是uf_xxx.h),一些例子程序(有JAVA、C++、Python、.NET,附带说明,可以参考一下),以及一个名叫NXOpen的目录,是NX Open系列头文件(以命名空间_开头的文件)的所在位置;
UGOPENPP:是Open C++的所在目录,里面头文件形式为
.hxx。
三、开始动手
首选要安装一个VS,我用的是2019版(与2017兼容),其他版本也可以。UG版本12.0(64位)。操作系统是WIN10。要注意的是不同UG版本的目录结构有些差异,但是要找的这些库和头文件都是类似的,可以用everything辅助查找一下。UG安装过程中如果选自定义安装的话,一定要勾选编程开发接口那一项。安装好这两个软件之后:

打开VS,依次点菜单 文件-新建-空项目,在源文件那里新建一个ugtest.cpp的空文件,然后在项目名称那里右键-属性;

注意项目配置,要选Debug(或release,Debug是指开发阶段的配置,开发完成后要发布的话要配置的是Release),平台一定要选x64,因为UG12.0提供的都是64位版本的库。看情况而定,如果是较旧版的UG可能是32位的。

然后就是配置属性的常规页,配置类型我这里选的是应用程序(.exe)。按个人需求,如果开发内部模式的程序一定要选动态库(.dl)。这一步是告诉编译器我们要输出的文件是哪种类型。

接着点C/C++页,在附加包含目录里加入两个存放头文件的路径(在VC++目录页的包含目录那里加也可以,区别是一个针对全局的配置,一个是针对该项目的配置)。这一步的目的是告诉编译器应该在哪里找我们用的头文件。

再接着,在链接器页,在附加库目录里添加UGOPEN文件夹。这一步是为了让编译器能找到要用的*.lib文件(这个并不是静态库文件,而是动态链接库的导出库文件,添加之后可以让程序在需要时自动加载dll文件。同样,在VC++目录页库目录配置效果相同)。

下一步,在链接器-输入页,加上在NXOPEN目录里所有的*.lib文件名。这一步的目的是告诉编译器,我们的程序要用到哪些动态库,如果少加会报错,“无法解析的外部符号…”。我添加项的如下:
libameopencpp.lib
libanimationdesigneropencpp.lib
liblinedesigneropencpp.lib
libmfgmlpopencpp.lib
libnxopencpp.lib
libnxopencpp_annotations.lib
libnxopencpp_assemblies.lib
libnxopencpp_bodydes.lib
libnxopencpp_cae.lib
libnxopencpp_cam.lib
libnxopencpp_diagramming.lib
libnxopencpp_diagramminglibraryauthor.lib
libnxopencpp_die.lib
libnxopencpp_display.lib
libnxopencpp_drafting.lib
libnxopencpp_drawings.lib
libnxopencpp_facet.lib
libnxopencpp_features.lib
libnxopencpp_fields.lib
libnxopencpp_formboard.lib
libnxopencpp_gateway.lib
libnxopencpp_geometricanalysis.lib
libnxopencpp_geometricutilities.lib
libnxopencpp_issue.lib
libnxopencpp_layer.lib
libnxopencpp_layout2d.lib
libnxopencpp_markup.lib
libnxopencpp_mechanicalrouting.lib
libnxopencpp_mechatronics.lib
libnxopencpp_modldirect.lib
libnxopencpp_motion.lib
libnxopencpp_openxml.lib
libnxopencpp_optimization.lib
libnxopencpp_options.lib
libnxopencpp_partfamily.lib
libnxopencpp_pdm.lib
libnxopencpp_physmat.lib
libnxopencpp_placement.lib
libnxopencpp_plas.lib
libnxopencpp_positioning.lib
libnxopencpp_preferences.lib
libnxopencpp_report.lib
libnxopencpp_routing.lib
libnxopencpp_shapesearch.lib
libnxopencpp_sheetmetal.lib
libnxopencpp_shipdesign.lib
libnxopencpp_sim.lib
libnxopencpp_tooling.lib
libnxopencpp_userdefinedobjects.lib
libnxopencpp_userdefinedtemplate.lib
libnxopencpp_validate.lib
libnxopencpp_visualreporting.lib
libnxopencpp_weld.lib
libnxopenjava_markup.lib
libnxopenuicpp.lib
libopenintpp.lib
libopenpp.lib
libufun.lib
libufun_cae.lib
libufun_cam.lib
libufun_die.lib
libufun_vdac.lib
libufun_weld.lib
libugopenint.lib
libugopenint_cae.lib
libugopenint_cam.lib
libvmathpp.lib
为了避免手动输入,可以使用cmd命令:
cd C:\Program Files\Siemens\NX 12.0\UGOPEN
dir *.lib > C:/Users/GGGGITFKBJG/Files/dependence.txt
然后在指定的文件夹下会出现一个dependence.txt文件,复制出来就行。

  1. 然后可以点确定关掉项目属性窗口,在工具栏解决方案配置那里,选择Debug-x64:

  2. 还有最重要的一步,添加环境变量。这一步的目的是,告诉编译器dll文件在哪找,如果这一步不加,编译可以通过,但是运行时会报错,“找不到xxx.dll”。在桌面此电脑图标上右键-属性,然后点左侧高级系统设置,高级-环境变量,在系统变量里找到PATH变量,编辑,加入UG的NXBIN目录:

  3. 到这里配置完成了,输入代码编译看一下:

// NX 12.0.0.27
// Journal created by GGGGITFKBJG on Thu Jul 18 21:43:04 2019 中国标准时间

//
#include <uf_defs.h>
#include <NXOpen/NXException.hxx>
#include <NXOpen/Session.hxx>
#include <NXOpen/BasePart.hxx>
#include <NXOpen/Expression.hxx>
#include <NXOpen/ExpressionCollection.hxx>
#include <NXOpen/NXObject.hxx>
#include <NXOpen/Part.hxx>
#include <NXOpen/PartCollection.hxx>
#include <NXOpen/PartLoadStatus.hxx>
#include <NXOpen/PartSaveStatus.hxx>
#include <NXOpen/Preferences_SessionModeling.hxx>
#include <NXOpen/Preferences_SessionPreferences.hxx>
#include <NXOpen/Session.hxx>
#include <NXOpen/Unit.hxx>
#include <NXOpen/UnitCollection.hxx>
#include <NXOpen/Update.hxx>

#include

int main()
{
NXOpen::Session* theSession = NXOpen::Session::GetSession();

NXOpen::BasePart* basePart1;
NXOpen::PartLoadStatus* partLoadStatus1;

try {//打开*.pat文件
	basePart1 = theSession->Parts()->OpenActiveDisplay("C:\\Users\\GGGGITFKBJG\\Files\\ug_work\\modeltest.prt", NXOpen::DisplayPartOptionAllowAdditional, &partLoadStatus1);
}
catch (NXOpen::NXException& e) {
	std::cout << e.Message() << std::endl;
	return -1;
}

NXOpen::Part* workPart(theSession->Parts()->Work());
//NXOpen::Part* displayPart(theSession->Parts()->Display());
delete partLoadStatus1;

std::cout << "Open model successfully." << std::endl;

//theSession->Preferences()->Modeling()->SetUpdatePending(false);//延迟更新,默认false

//更新参数
NXOpen::Expression* expression1(dynamic_cast<NXOpen::Expression*>(workPart->Expressions()->FindObject("Length")));
NXOpen::Unit* unit1(dynamic_cast<NXOpen::Unit*>(workPart->UnitCollection()->FindObject("MilliMeter")));
//workPart->Expressions()->EditWithUnits(expression1, unit1, "1435");

for (auto p = workPart->Expressions()->begin(); p != workPart->Expressions()->end(); p++) {
	std::cout << (*p)->Name().GetText() << ", ";
	std::cout << (*p)->Equation().GetLocaleText() << ", ";

	std::cout << (*p)->Type().GetLocaleText() << std::endl;
}

std::cout << "Updated model successfully." << std::endl;

//保存
NXOpen::PartSaveStatus* partSaveStatus1;
partSaveStatus1 = workPart->Save(NXOpen::BasePart::SaveComponentsTrue, NXOpen::BasePart::CloseAfterSaveFalse);

//检查保存状态
if (int unsaved = partSaveStatus1->NumberUnsavedParts()) {
	std::cout << unsaved << " part(s) cannot be saved." << std::endl;
}
std::cout << "All parts saved successfully." << std::endl;
delete partSaveStatus1;

return 0;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
这段代码的作用是打开一个已有的部件,修改它的参数保存并关闭,使用了外部模式。如果能编译通过则说明环境配置没有问题。如果不通过,请检查上述步骤是否都正确。

四、一些提示
快速地熟悉编程接口是很重要的,最好的方式是看文档+代码实操。在C:\Program Files\Siemens\NX 12.0\UGOPEN\SampleNXOpenApplications目录里有一些NXOpen的例子代码并附有说明,可以做为参考。
另外UG提供了一个很有用的功能,录制操作记录,并导出成所选的代码文件。具体在菜单里可以选择:

然后在工具里可以开始和停止录制:

这是最有用的功能,大部分情况下只要手动操作一次,就可以找到对应的代码实现,省去了查文档猜函数的烦恼。
操作记录的代码都是以内部模式的形式记录的,要做成外部模式稍做修改即可。
注意录制的时候如果有视图操作(放大,旋转等),会把这些也记录到代码中,所以录制过程中尽量只做有效操作,这样可以减少复杂度。
录制的代码中,markid相关的可以删除掉,它是在交互模式中用以undo,redo操作的。
NXOpen c++的录制代码中并没有异常处理,需要手动修改。

OK,环境搭建就此完成,接下来就是学习制做想要的功能了。

开发环境配置对于初学者来说是一件头疼的事,本人清楚记得几年前上C语言课的时候费了七八个小时来配置VC++,跟着视频同步做也一直调不好。主要是因为在脑子里关于这块知识是一团浆糊,而且几乎每个人的系统都不太一样,遇到稍微的一些变化的就束手无策了。建议学习一些C程序编译和链接相关的知识,明白了这些过程以后,再遇到这种问题就可以自己解决了。

参考书有
《深入理解计算机系统》(CSAPP)的第七章
《程序员的自我修养–库的装载、链接与执行》

最后祝大家以及自己学习进步!!

2019.07.20 02:06
————————————————
版权声明:本文为CSDN博主「wanghy1995」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sinat_27953939/article/details/96472341

  • 0
    点赞
  • 0
    评论
  • 6
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值