iCAx开思网

标题: 浅谈UG OPEN C API开发中的用户出口(user exits) [打印本页]

作者: 深夜摔键盘    时间: 2005-5-14 08:26
标题: 浅谈UG OPEN C API开发中的用户出口(user exits)
,那天碰到一个问题,文档没有说清楚(也可能是我英文理解有问题),日志中粗略整理了一下,大家也来谈谈自己的看法★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
2005.5.9
好久都没有做UG二次开发内容的事情了。今天我想做一种动态的菜单机制。譬如,在进入Modeling模块后,在主菜单栏上显示我的菜单文件。本以为很简单的一个事,却烦了我一下午。
  
1. 我先在startup文件里也了一个men文件,内容如下:
VERSION 120
EDIT UG_GATEWAY_MAIN_MENUBAR
MODIFY
APPLICATION_BUTTON UG_APP_MODELING
LIBRARIES mainModule.dll
MENU_FILES mytest.men
END_OF_MODIFY
没有心思去搞懂菜单脚本的语法,直接从文档里抄了一段出来。大致意思是想在进入modeling模块时,加载我写的一个库和我的菜单文件,我的菜单中的每一项都和库中的回调函数相连的。有必要记住的就是这儿只能是APPLICATION_BUTTON型的Button有这种权限。
  
2. 然后我在application文件夹下放了库文件mainModule.dll和菜单文件mytest.men。
菜单文件的内容如下:
VERSION 120
EDIT UG_GATEWAY_MAIN_MENUBAR
AFTER UG_APPLICATION
CASCADE_BUTTON RE_MODELING
LABEL   ENTRY
END_OF_AFTER
  
MENU MainModule
BUTTON DATA_IMPORT
LABEL Import data...
ACTIONS DataImport_cb
END_OF_MENU
大致意思是在Application菜单后显示我的菜单。
作者: 深夜摔键盘    时间: 2005-5-14 08:26
3 然后,我就按照文档的一个例程,在库中做了如下工作:
/////////////////////////////////////////////
//菜单动作表,将回调函数名称与菜单项连接起来
/////////////////////////////////////////////
static UF_MB_action_t action_table[]=
{
  {"DataImport_cb",(UF_MB_callback_t)DataImport_cb,NULL},
  { NULL, NULL,NULL}
};
//菜单回调函数
static UF_MB_cb_status_t DataImport_cb(UF_MB_widget_t widget,UF_MB_data_t client_data,UF_MB_activated_button_p_t call_button )
{
  UF_initialize();  
  uc1601("read data",1);
     UF_terminate();
  return UF_MB_CB_CONTINUE;
}
extern void ufusr( char *parm, int *returnCode, int rlen )
{
    /* Initialize the API environment */
    UF_initialize();  
  uc1601("read data000",1);
  UF_CALL(UF_MB_add_actions(action_table));
    /* Terminate the API environment */
    UF_terminate();
}
然后程序运行时出错,说我的菜单没注册action,跟踪调试了一下,发现根本就没有进入我的库文件的入口ufusr。我换成了ufsta入口,结果就可以了。我的目的达到了。但是却开始怀疑了,为什么ufusr入口不行?
作者: 深夜摔键盘    时间: 2005-5-14 08:27
道理应该是很简单,UG就规定必须是ufsta吧。可我没有从文档中发现有这样的硬性规定。而且长期以来,我养成了一种意识,认为application中的dll大都是ufusr的。究竟ufusr和ufsta它们都是什么东西???
  
文档对ufusr是这样描述的:Internal Open API Entry Point. You use ufusr as a main function entry point for all Internal Open API programs. The ufusr function may also be used for user exits. 。
很明显,文档声称对于所有的内部OPEN API程序都可以使用ufusr作为入口,结果在上面的情况中就不可以了。后面那句说ufusr也可以来作为用户出口,什么是用户出口呢?打开uf_exit.h文档,在over view里看一看。
  
在NX中,用户出口功能可以让你在预先指定的位置自动运行Open C API程序。出口有很多,如果你定下了这些出口中的一个,譬如ufsta,NX会检查一下,看看你是否定义了一个指向你的OPEN C API程序所在位置的”指针”,如果你定义了这个”指针”,那么NX就会运行这个程序。这个指针是一个环境变量(UNIX)。
  
最后一句是关键的,所谓的”指针”是一个环境变量,但括弧里说是在Unix中是这样,在Windows里怎样?我估计这块文档从未更新过,在windows里,我们常常要告诉UG,我们的startup文件夹在哪儿。
  
这些所谓的”出口”,就是DLL文件的输出函数。有一个问题我没想明白,void ufusr(…..),这样的一个函数,并没有对其使用输出修饰符dllExport,或者在def文件中声明,它是怎样输出的呢??????后来我也弄明白了,extern在搞怪。
  
文档中对出口如何使用有如下说明:写一个能实现你的需求的程序,如果是内部程序必须成对使用UF_initialize() 和UF_terminate(),这个和我们使用ufusr作为出口是一样的。定义指向你写的程序的指针。这可以认为是个文件指针,它所指向的内容则是对你的程序文件的描述。文件指针的定义要依赖所用的操作系统,不同的操作系统有不同的环境变量格式,当UG遇到一个用户出口时,系统就会检查指向OPEN C API程序所在位置的环境变量是否存在,如果在指定位置发现了OPEN C API程序,就自动执行它,然后返回UG。
  
对于这段话的理解:假如想让UG在保存文档时自动运行我们指定位置的程序,UG的文档保存就是一个出口,当用户点击”保存文档”菜单时,UG会调用操作系统的功能查看环境变量USER_FILE 是否被设置为用户程序所在的路径了,如果用户的程序存在,那么就会自动调用用户程序,此时用户程序的入口函数为ufput。UG OPEN C API中,每个出口都有一个环境变量和一个规定的用户程序入口点。但ufusr例外,它没有环境变量,但它是用户程序的入口点。
  
对于用户程序的ufsta入口函数,那么它采用的UG出口就是NX Startup,就是说如果我们想让UG一启动时就自动运行我们的程序,那么就必须设置环境变量USER_STARTUP为用户程序所在的目录。事实上我们并没有设置USER_STARTUP变量,而是在$UG_BASE/ugii/menus/custom_dirs.dat中指定的程序位置。那么UG在启动时,就首先检查custom_dirs.dat文件中所指定的位置是否存在用户OPEN C API程序,如果用户程序存在,就自动从ufsta入口执行它。
作者: zhaobinbob    时间: 2005-5-14 18:28
分析的多好啊!!
作者: zzx001    时间: 2005-5-14 18:34
好啊,对我们很有帮助!!!
作者: 深夜摔键盘    时间: 2005-5-14 19:38
略为分析一下为什么ufusr,ufsta这样的user exit,在用户DLL中作为程序入口点时,不需要__declspec(dllexport)或者def文件来声明,但生成的DLL依然能够成为输出函数的原因。
  
动手试一下就知道了,以前没大注意这个,这也算是一种程序技巧。我测试是能通过的,但不知道UG是不是这么搞的。
  
1.建一个DLL工程,在.c或.cpp文件中声明一个函数,譬如在A.cpp中,
__declspec(dllexport) void fun(void);
  
2.然后在头文件A.h中添加如下代码:
extern __declspec(dllexport) void fun(void);
  
3.编译连接后,生成动态连接库A.dll
  
这样,假如fun函数就看作是我们的ufusr。然后我们做二次开发,建一个DLL工程B吧,
1.在B.cpp中,#include "A.h"
2.实现函数fun,譬如:
  
void fun(void)
{
   printf("hello world\n");
}
3.编译连接,生成B.dll,使用查看DLL文件的工具,就能够看到B.dll中存在一个名为fun的输出函数。
  
我以为这就是为什么我们不对ufusr/ufsta这样的函数做输出修饰,而它们依然可以输出的缘由。
作者: answer1977    时间: 2005-5-15 17:01
好贴总是要顶的,键盘兄,能告知你的QQ吗,方便求教
作者: fourwood    时间: 2005-5-15 21:24
看了这个,再也不用C来进行UG二次开发了。
作者: h2023197    时间: 2005-5-16 14:28
真好啊,对我学习挺有帮助的!!
谢谢键盘兄!!
作者: zwg_xl    时间: 2005-5-16 16:18
很好,受益匪浅!谢谢!
作者: qingwufy    时间: 2005-5-17 21:49
谢谢键盘兄
作者: tokevinyang    时间: 2008-10-22 10:03
确实是好东西
老帖我也要顶




欢迎光临 iCAx开思网 (https://www.icax.org/) Powered by Discuz! X3.3