当前位置: 首页 > 工具软件 > grip > 使用案例 >

UG二次开发C#通过GRIP实现调用C++项目并互相传递参数

易骁
2023-12-01

背景

最近由于项目需要利用C#外部模式调用C++写的UG二次开发内部模式模块,需要将部分C#计算的参数传递给C++模块并将结果返回C#。所以研究了下利用GRIP作为中介调用。(事实上一些简单的参数直接写到part的属性中,再由另一方查找读取更加方便)

本文用的UG版本为8.5

一.C#部分

1.UF_call_grip函数提取

由于我使用的版本的UFSession中没有直接呼叫Grip的函数UF_call_grip,因此需要将UF_call_grip从libufun.dll中提取出来使用。

[DllImport("libufun.dll", CallingConvention = CallingConvention.Cdecl, 
CharSet = CharSet.Ansi, EntryPoint = "UF_call_grip")]
internal static extern int _CallGrip(string grip_executable, int argument_count, ref Args gruf_arg_list);
public static void CallGrip(string grip_executable, int argument_count, ref Args gruf_arg_list)
{
	JAM.StartUFCall();
	int num = _CallGrip(grip_executable, argument_count, ref gruf_arg_list);
    JAM.EndUFCall();
}

CallGrip即为提取出的呼叫函数

2.要传递和接收参数的初始化

以传递一个C++需要的Char* 为例,传递一个文件路径过去:

string path = "D:\\temp\\test.txt";
IntPtr init = Marshal.StringToHGlobalAnsi(path);
int grip_arg_count = 1;
Args [] grip_arg_list = new Args[1];
grip_arg_list[0].address = init;
grip_arg_list[0].length = 0;
grip_arg_list[0].type = UFConstants.UF_TYPE_CHAR;

这里的Args是个结构体对应着UF_call_grip
中的UF_args_s结构体,address就是要传递的参数的指针

//.cs
    [Serializable]
    public struct Args
    {
        public IntPtr address;
        public int length;
        public int type;
    }
//.c++
struct UF_args_s 
{   int   type;            /* one of the types, UF_TYPE_DOUBLE, 
                                  UF_TYPE_DOUBLE_ARRAY, UF_TYPE_TAG_T, 
                                  UF_TYPE_TAG_T_ARRAY, UF_TYPE_CHAR or 
                                  UF_TYPE_CHAR_ARRAY. */ 
   int   length;        /* the number of elements in an array, for 
                                  types UF_TYPE_DOUBLE_ARRAY, 
                                  UF_TYPE_TAG_T_ARRAY or UF_TYPE_CHAR_ARRAY. */ 
   void  *address;        /* A pointer to an array of the given 
                                  type and length.  Note that for an array 
                                  of UF_TYPE_CHAR, if the argument list 
                                  is built by the Open program, it must 
                                  initialize this array whether it is input or 
                                  output.  An output array can be initialized 
                                  by setting the first byte to '\0'.  */ 
};    

3.调用CallGrip呼叫GRIP

CallGrip("D:\\temp\\test.grx", grip_arg_count, ref grip_arg_list);

二.Grip部分

//.grs
string/dir(2,132)
string / tempPath(132)  $接收path的参数

dir(1) = ENVVAR/'UGII_USER_DIR',ASK
dir(2) = dir(1)+'\template\test.dll' $要调用的内部模式的C++dll路径

ufargs / tempPath  $从C#接收参数

grargs / tempPath $初始化要传递到dll参数列表
XSPAWN/UFUN,dir(2) $调用内部模式的dll

halt

c#中的path通过ufargs传递到了tempPath中,而grargs函数将tempPath注册到将要调用的dll的参数列表中,最后通过XSPAWN函数调用dll就将参数传递进去了

参数具体说明可GRIP帮助文件

三.C++部分

UF_ask_grip_args用来接收传递的参数

char path[133];
int GRIP_ARG_COUNT = 1;
UF_args_t    grip_arg_list[GRIP_ARG_COUNT];
grip_arg_list[0].type    = UF_TYPE_CHAR;
grip_arg_list[0].length  = 0;
grip_arg_list[0].address = path;
UF_ask_grip_args (GRIP_ARG_COUNT, grip_arg_list);
//结果:path = "D:\\temp\\test.txt"

这样,path就成功地从C#传递到C++中了。

总结

同样的可以使用UF_set_grip_args对上文中grargs初始化的参数列表的值进行重设,从而实现了将参数回传给GRIP。
而在GRIP中直接对诸如tempPath之类的从C#接收的参数进行修改的同时,C#中的参数如path也会相应修改,从而实现从GRIP传递参数给C#。

 类似资料: