最近由于项目需要利用C#外部模式调用C++写的UG二次开发内部模式模块,需要将部分C#计算的参数传递给C++模块并将结果返回C#。所以研究了下利用GRIP作为中介调用。(事实上一些简单的参数直接写到part的属性中,再由另一方查找读取更加方便)
本文用的UG版本为8.5
由于我使用的版本的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即为提取出的呼叫函数
以传递一个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'. */
};
CallGrip("D:\\temp\\test.grx", grip_arg_count, ref grip_arg_list);
//.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帮助文件
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#。