Cadence Skill 跳坑笔记 关于 ipcSkillProcess 的调用

 Cadence Skill 跳坑笔记 关于 ipcSkillProcess 的调用

老wu最近开发新的Cadence周边工具–阿狸狗大杀器,需要实现Allegro与外部的exe程序进行异步通信的功能。而Allegro中与process异步通信相关的skill function有 ipcBeginProcess 及 ipcSkillProcess。

 

ipcBeginProcess 这个函数可以让allegro启动一个外部的程序并通过stdin stdout交换数据,参考手册中关于ipcBeginProcess的使用定义如下:

 

[php]
ipcBeginProcess(
t_command
[ t_hostName ]
[ tsu_dataHandler ]
[ tsu_errHandler ]
[ tsu_postFunc ]
[ t_logFile ]
)
=> o_childId
[/php]

然后你可以写一个可执行程序,通过stdin及stdout与allegro主程序交换数据

[php]
#include <stdio.h>

#define bufflen 4096

int main(int argc, char *argv[])
{

char buff[bufflen];

while (1) {
gets(buff);
{ int i;
for(i=0; i < strlen(buff); i++)
buff[i] = toupper(buff[i]);
}
printf(buff);
fflush(stdout);
fflush(stdin);
}

return 0;
}
[/php]

在allegro中通过skill调用上面的可执行程序
[php]
procedure( dataH(cid data)
printf(“cid: %L Msg: %s\n” cid data)
)

procedure( simErr(cid err)
printf(“Error %L Msg: %s\n” cid err)
ipcKillProcess(cid)
)

procedure( simTerm(cid exit)
printf(“Simulator expired with exit status = %L %d\n” cid exit)
)

procedure( test()
cid = ipcBeginProcess(“d:\\SkillTest\\Intermediary.exe” “” “dataH” “simErr” “simTerm” “”)
ipcWriteProcess( cid “hello\n” )
x = ipcReadProcess( cid 20 )
when(x printf(” New string : %s”, x ))
)
[/php]

 

这样虽然可以实现allegro与外部可执行程序间的交互,但是对于阿狸狗大杀器应用来说,还不够,老wu希望能够实现在阿狸狗大杀器中能够直接调用allegro中的skill function。

在skill手册中发现了ipcSkillProcess 这个函数,貌似可以实现老wu想要的功能。

ipcSkillProcess 函数的定义如下:

[php]
ipcSkillProcess(
t_command
[ t_hostName ]
[ tsu_dataHandler ]
[ tsu_errHandler ]
[ tsu_postFunc ]
[ t_logFile ]
[ x_cmdDesc ]
[ x_resDesc ]
)
=> o_childId
[/php]

Invokes an Operating System process capable of executing SKILL functions in the parent process. Opens two additional channels to the child process that let the child send and receive the results of SKILL commands.

Note: The maximum number of child processes is limited by the system resources and a warning message displays when the fileDescriptor limit is exceeded.

关于ipcSkillProcess的外部可执行程序示例代码如下:

[php]
Suppose we have a C program, sample.c:

/**********************************************
* Sample process for executing SKILL commands
* in parent process.
**********************************************/
#include “stdio.h”
#define skill_cmd 3
#define skill_result 4

main(int argc, char **argv)
{
int status;
char s[100];

sprintf(s, “%s”, “(let () (println \”Hello world \”) (1 + 1))”);
printf(“Executing %s”, s);
fflush(stdout);
status = write(skill_cmd, &s[0], strlen(s));
status = read(skill_result, &s[0], 100);
s[status] = ‘\0’;
printf(“Result = %s”, s);
fflush(stdout);
exit(0);
}
[/php]

此时,老wu已经默默入坑了,被坑了一下午,~~~~(>_<)~~~~

上面的代码没有问题,可以在windows下编译通过,但他娘的,这里的ipcSkillProcess是只适用于linux环境下的allegro的,windows下有问题,cadence的说明书编写人员也不注明一下,他娘的鄙视你,?

具体windows是什么问题的呢?为了避免后来者再掉到坑里头,老wu在这里注明一下

仔细查看ipcSkillProcess的说明,你会发现这么一段话
”The SKILL command channel is by default bound to file descriptor number 3 in the child process. In addition to whatever input and output the child process may perform, it can write SKILL executable commands on this descriptor that are in turn sent to the parent to be executed. The parent executes these commands during the next cycle of SKILL’s top level without interrupting the current evaluation. The result of this execution is sent back to the child over the SKILL result channel, which is by default bound to file descriptor number 4 in the child process.”

file descriptor 看到没有,allegro与外部程序通信是通过file descriptor来实现的,file descriptor number 0和1 用于 stdin及stdout,即跟上边提到的ipcBeginProcess的一样。而file descriptor number 3用于外部程序给allegro发送skill命令,allegro可以直接执行该命令,而file descriptor number 4返回skill 命令的执行结果给外部的可执行程序,当然,file descriptor number可以通过调用参数x_cmdDesc及x_resDesc进行指定到别的值,例如指定9和10

那file descriptor是什么呢,为什么会被file descriptor给坑到?

通过维基百科,世上最自由的百科全书老wu知道,File descriptor即文件描述符,是计算机科学中的一个术语,是一个用于表述指向文件的引用的抽象化概念。

文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。

看到没,文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。而在非UNIX/Linux 操作系统上(如Windows),无法基于这一概念进行编程。

在UNIX/Linux平台上,对于控制台(Console)的标准输入(stdin),标准输出(stdout),标准错误输出(stderr)也对应了三个文件描述符。它们分别是0,1,2。

Windows下的文件描述符和信号量、互斥锁等内核对象一样都记作HANDLE, 所以上边的例子,如write(1, &s[0], strlen(s));和read(0, &s[0], 100);在windows下调用是成功的,相当于往stdout写数据和从stdin里读数据。

windows的控制台只有stdin、stdout、stderr这三种标准的输入输出通道,所以在windows中write(3)或者read(4)这样的操作是会使程序异常退出的。

但老wu的阿狸狗大杀器又要在外部程序中调用allegro中的skill,怎么破?

老wu花了2个小时,翻遍了所有skill相关的function,终于发现了个可以实现这个功能的折中方法:

skill中有“stringToFunction”这么一个函数,可以将字符串穿换成可调用的skill代码,如:

f = stringToFunction(“axlDBControl(‘activeLayer, \”ETCH/TOP\”)”)

会返回:”funobj@0x2649bca2098″ 这个f就是代表了axlDBControl(‘activeLayer, \”ETCH/TOP\”)这么一个skill操作代码,这段代码的功能是将当前的calss及subclass切换为:ETCH/TOP

然后再通过”apply”这函数就可以实现真正的函数调用了,如:apply(f nil)

所以,在阿狸狗大杀器中调用allegro中的skill并获取函数返回值的折中方案是:

通过 ipcBeginProcess 启动外部程序,然后外部程序通过stdout将需要执行的skill语句传给allegro,在allegro中通过异步的方式获得外部程序传进来的skill语句字符串,在通过stringToFunction转化成可调用的skill代码,然后通过apply函数来实现真正的skill function调用,并获取函数调用返回值,通过ipcWriteProcess这个函数将结果返回到外部程序中。

当然了,老wu水平有限,如果您有更加优雅的解决方案,还望不练赐教,请你推油,O(∩_∩)O~

吴川斌

吴川斌

8 Comments

    夜
  • 吴老师,请问“在allegro中通过异步的方式获得外部程序传进来的skill语句字符串”中“异步的方式”是如何实现的呢?

  • yuanyiping
  • 请教吴老师,我的外部可执行程序。如果只有stdin和stdout相关的命令,可以正常用。想加上别的功能,通过skill再运行外部程序就没反应了,只是在allegro弹出一个send successful的窗口。注释掉这部分额外功能代码,就正常了。从吴老师上面写的来看,您的外部程序应该也是有其它功能的。吴老师是否碰到过这个问题,请指教,谢谢。

      yuanyiping
    • 换了电脑就没问题了,在一个电脑上复制出的程序修改可能就有这个问题。

  • 吴老师,破解完16.6,每次打开orcad 都会出现这个,这是我没破解好吗?

    • 应该是系统问题 跟软件破解物管 如果是破解不成功 启动软件提示的应该是license failed

      • 应该是公司电脑有问题,我发现,有保密软件

        • 那就没办吧了 O(∩_∩)O~

  • 好厉害[/鼓掌]

Leave a Reply