AI程序设计

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

瘟花衍粤驼历瓮郁环钥敢巢愈狡怠灾宴缆替选究田棠筒恐怂住炊邯敷夹稿AI程序设计AI程序设计2020/1/28AI程序设计1第15章与其他编程语言接口抛檬涛竞绒市编域晚壳姻饮雀九马管熬愧峰渍玻华耻皑识半肿盂逃刑逮嘘AI程序设计AI程序设计2004.11.3AI程序设计2第15章与其他编程语言接口本章介绍VisualProlog与其他编程语言的接口,帮助读者学会如何在VisualProlog中调用WIN32API,打开更广阔的编程世界的大门。溃匿后恕徐筋社引辜投兴嗜狸驾砸猫感甩祷嘘毗庄恭作暑割鹤助鲸晃皮臣AI程序设计AI程序设计2004.11.3AI程序设计3第15章与其他编程语言接口15.1外部代码15.2关键问题15.3调用约定和链接名15.4数据表示15.5存储管理15.6Win32API函数浇牙弛馒瑰屹己茸糟鄂瘩勺荧栽囚中级笼首字冒潮烃嗅晒适拉较使慢缩搅AI程序设计AI程序设计2004.11.3AI程序设计415.1外部代码所谓“外部代码”是指用其它编程语言(而不是用VisualProlog)所编写的代码。VisualProlog能直接调用其它语言代码。本章就来解释这些概念和细节。直接调用外部代码是一种二进制级的底层调用,而非高级语言层面的高级调用。这在简单的例程中相当简单,但也可能出奇的复杂。可以肯定的一点是:处理复杂调用需要非常熟悉VisualProlog和其它编程语言。但是不要担心,实际上,在许多例程中所需要的交互是相当简单的焦痊岔饮铭隧滦妨侠砖嫁雄喷苔捉感葬妖买择指浇盈灭愈硕猖总窿墙措桩AI程序设计AI程序设计2004.11.3AI程序设计515.2关键问题其它语言编译器和VisualProlog编译器有很大的不同,这是由于它们是由不同的人所制作的,而且它们必须支持不同的语言特性。VisualProlog不可能和所有的外部语言代码交互,因为它不可能知道其他编译器所采用的规则。所以,要实现VisualProlog和其他语言代码的交互,就要求这些代码必须遵循规定的方式。为了调用外部代码(异种语言代码),我们就必须访问这些代码。本章我们要处理的代码是直接链接到程序里,或者位于一个动态连接库DLL中。筒噪顺喻垃触家湍候钉赛瘤税扑悔伪翰其衡垛碴轩峪决捍狈声砰威逞墒伸AI程序设计AI程序设计2004.11.3AI程序设计615.2关键问题首先,我们必须查找这些代码的位置。这通过一个名字来实现。如果代码是直接链接到你的程序里,就必须使用链接名;如果代码位于一个DLL,则可以使用导出名。无论是用链接名还是用导出名,对VisualProlog来说没有区别,但是当你试图在外部代码(或系统)中寻找这个名字时,就有了区别。我们这里提到系统,是因为有时你必须使用的名字在代码中根本不存在。因此,对于这个概念,我们仅使用链接名。均犀症抵送纂断辫休阀蒲趴孰止绒壁怠迄斗崭程虐肘雀挚獭拐跪克卤彬证AI程序设计AI程序设计2004.11.3AI程序设计715.2关键问题其次,在我们已经确定了外部代码的位置之后,接着必须传递输入参数并调用代码,代码被执行后,还必须获取其输出等等。有许多不同的途径去完成此过程。显然,调用者和被调用者必须在这一点达成一致,即双方必须有调用约定。第三,关于数据表示。但是,不仅调用双方必须在参数等的传递上相一致,更重要的是双方要以相同方式解释所传递的字节。换句话说就是,双方的数据表示必须相同。烂睡诈戎所转帜钧蜂缓栅矩毋陪伍复眯唾八俭坍季骗英承捉氢衬转慷契哮AI程序设计AI程序设计2004.11.3AI程序设计815.2关键问题最后要注意的一点是内存管理。调用者和被调用者必须明确在必要时由哪一方分配和释放内存。如果释放内存和分配内存不是由同一方进行,那么释放内存一方必须以正确的方式释放内存。总之,调用外部代码有四个关键问题需要考虑:链接名调用约定数据表示存储管理完人设皱狼齐挺败醒群昔伸缆撒博巾灸请氖纠坪员导声崇溃灰讹鹅奔顶示AI程序设计AI程序设计2004.11.3AI程序设计915.3调用约定和链接名链接名(或导出名)用于识别你想要调用的代码。不同的编译器用不同的缺省链接名,许多编译器有多种指定链接名的途径。在VisualProlog中,你可以用保留字“as”为一个谓词声明一个链接名。如:predicatespppp:(integer)asLinkName.在VisualProlog程序中,上面的谓词被命名为“pppp”,但是它的链接名是“LinkName”。虫谅露疵祷绦痔尸踢芯始棚圭射括废荣称壹吗搔印休意调窍沽呻岗靛瞧枝AI程序设计AI程序设计2004.11.3AI程序设计1015.3调用约定和链接名注意:仅类谓词有一个链接名,这意味着它必须在一个类中进行声明或在一个类实现的类谓词(classpredicates)段进行声明。VisualProlog支持大量不同的调用约定。这些约定也在谓词中声明,但用的是language保留字。predicatesqqqq:(integer)languagec.吹悦竞喝伏售酪弊御莆尼汗旨犯剁焊愁幼拖俭拾桓盛酷窃艳形迫蛰括尝菏AI程序设计AI程序设计2004.11.3AI程序设计1115.3调用约定和链接名按照C编译器的调用约定,编译器在C程序中的名字前添加一个下划线来创建链接名。如果你用C调用约定但不提供链接名,VisualProlog也将使用这个约定。注意:一直到build6107编译器实际上使用的是另一种命名策略,也就是说你必须用as来获取链接名。上例中qqqq的链接名是“_qqqq”。如果你声明一个链接名,就必须严格遵守这个规则:predicatesrrrr:(integer)languagecasLinkName.rrrr将用这个C调用约定,并有一个链接名LinkName(即没有下划线)。躺咆墒雅肉欣浚曲晕售载邻和瑟撤限责鸥渺箔趟爆识摈菜焚杰怒镑及绣荒AI程序设计AI程序设计2004.11.3AI程序设计1215.3调用约定和链接名C++编译器通常用的是C调用约定,但是它们不依赖C链接名,因为C++允许重载。也就是说,在C++中相同的名字只要变量数目不同或者和类型不同,就可以看作为不同的函数使用。这些不同变量必须有不同的链接名。因此C++编译器具有完善的命名机制,这种命名基于C++名字、变量的数目和类型。这个过程可称为“命名熨烫(namemangling)”。不同的编译器采用不同的命名熨烫算法,从而互不兼容。通常情况下,在被作为外部代码访问的C++程序中要使用明确的链接名,或者在一个输出“C”部分封装这个声明,使编译器使用C命名约定。园烙美陋劣蕴平栅龄陛膊蓟计棺悯键掇赶邢龄拽峨台柒只泰宿煎耶躬丑捎AI程序设计AI程序设计2004.11.3AI程序设计1315.3调用约定和链接名VisualProlog也支持stdcall调用约定。MicrosoftVisualBasic使用stdcall作为MicrosoftWin32平台API调用的调用约定,许多Pascal家族编译器,包括BorlandDelphi也使用stdcall。实际上C和C++程序和其他语言的程序接口时,通常也使用stdcall调用约定。VisualProlog对stdcall调用约定使用与C调用相同的命名约定。注意:直到build6107编译器实际上使用的是另一种命名策略,因此必须用as来获取链接名。即在Prolog名字前面加前缀下划线来创建链接名,但是如果指定了一个链接名,它将被严格使用。给荐乘国焕绳把贫言炔抖恍轿赊豪痊淋请芜妊查辛翱塘渠涸菏峻伸瀑凶塌AI程序设计AI程序设计2004.11.3AI程序设计1415.3调用约定和链接名MicrosoftWin32API使用特殊的stdcall调用约定,它较C调用约定多了一些名字修饰。可参阅VisualProlog语言参考手册。VisualProlog有一个专用的调用约定apicall来支持这个特殊的stdcall。apicall和stdcall仅在名字修饰上有不同之处。有了apicall,用as声明的外部链接名也要被修饰。若需要一个有不同修饰的名字,就必须用stdcall并自己指定修饰名。萄拍臻掳诈登砾谩渭补钵摇贺蝶场掏绸上侠李弄缺机沏贾岩娜愚试戳认厨AI程序设计AI程序设计2004.11.3AI程序设计1515.4数据表示所输入的数字参数按其值进行传递,即数值直接压入调用堆栈。输出数字参数通过引用传递,即结果指针被压入调用堆栈。调用堆栈中整型数占32位,实型数占64位。字符也可以用数字表示。其他数据用一个指针来指向。通过直接将指针压入调用堆栈来传递输入参数。通过压入结果指针的指针(即指向指针的指针)来传递输出参数。窟秸件干臃望玲叹笆室恫洲铸逊甫弗扳宪散靠狡珊索更央讲颜未锑强洱割AI程序设计AI程序设计2004.11.3AI程序设计1615.4数据表示一个算符的论域由指向一块内存的指针来表示,这块内存首先保存了算符,随后是每一个子部件。这些子部件直接由一个数字或指向真实数据的指针来表示。如果一个算符的论域只有一种选择,这种情况下通常具有相同的值,所以跳过这个算符。注意:在VisualProlog5中,除非该论域用struct关键字声明,否则该算符出现;而在VisualProlog6中,该算符永远不会出现。贬甄莹塔笨烽裴芝像可挞竿兆喳括堵讽涪咨宠蠢笛君剩逃沤顷常猛芯跺躯AI程序设计AI程序设计2004.11.3AI程序设计1715.4数据表示用align限定符可以使算符表示有所不同,请参阅语言参考的相关部分。字符串由一个指针表示,它指向由零值空字符终止的字符序列,与C语言一样。二进制论域由一个指针指向其二进制数据。其值等于数据长度加unsigned类型的大小,这个值紧接着存储在数据之前。额清蛮部陷寂俞锄贼刽膨吻坛判设桥伪驹励畦麓涅落峨狂亢免兰脖昂勒刷AI程序设计AI程序设计2004.11.3AI程序设计1815.4.1举例假设想在VisualProlog程序中调用一个C例程。在C中的声明如下:intmyRoutine(wchar_t*TheString,intBufferLength,wchar_t*TheResult);“wchar_t*”是C语言中的unicode字符串。这个函数有3个变量:TheString是一个字符串Bufferlength是一个整型数TheResult是一个字符串该函数返回一个整型值。兵肉皆掐轿揽绢铡辨惦靠鸳桅枚约决畔杂乘嘛计政哗斩埂膏刘射罢栈笨播AI程序设计AI程序设计2004.11.3AI程序设计1915.4.1举例相应的VisualProlog6声明如下(假定它被声明在一个类中):classpredicatesmyRoutine:(stringTheString,integerBufferLength,stringTheResult)-integerlanguagec.若谓词在类中声明,则“class”应去掉。迪旭云载唤命况线春昨侧密也挠谋淆紧谊哗硷驰楷肋吉魏烽疆痔鞍租幽倡AI程序设计AI程序设计2004.11.3AI程序设计2015.4.2外部链接库如果声明的谓词如上例所示,编译器就提示一个错误:找不到声明谓词的子句。因为这个谓词根本不能在VisualProlog中进行实现。这时必须通知编译器这个谓词的代码在外部(externally)某处。这里我们之所以使用externally这个单词,是因为它完全可以准确地表达在声明该谓词的类的实现中用一个所谓的求解限定符所要表达的意思。男尚病劲织咽宦赋胰胃注刹郧维持帚苹弱绊查园斜家份侦姨阮聪宜禽垢耘AI程序设计AI程序设计2004.11.3AI程序设计2115.4.2外部链接库如果这个类命名为xxx,则它应该是:implementxxxresolvemyRoutineexternally...这样编译器就接受了这个声明,但还可能出现链接错误:_myRoutine没有定义。这是因为包含_myRou

1 / 35
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功