包的定义¶
基本语法¶
正如我们在本章所了解的一样,package
是一种允许我们对定义进行组织(包含其它包的定义)的Modelica实体。package
的语法定义与其它Modelica定义有很多共同点。定义包的一般语法是:
package PackageName "Description of package"
// A package can contain other definitions or variables with the
// constant qualifier.
end PackageName;
包定义可用encapsulated
限定词作为前缀。我们将在考察的Modelica的查找规则时进行进一步讨论。
如果必要包也可以进行嵌套例如:
package OuterPackage "A package that wraps a nested package"
// Anything contained in OuterPackage
package NestedPackage "A nested package"
// Things defined inside NestedPackage
end NestedPackage;
end OuterPackage;
实际上,包嵌套十分常见。这使我们能够表达复杂的分类。
文件夹储存¶
虽然我们将整个Modelica定义库存作为一系列嵌套的包储存在单一的文件内,但至少有两个原因令这种做法不可取。首先,由于文件长度和缩进层次,所得到的文件将相当没有可读性。然后,从版本控制的角度来看,将库分成更小的文件可以帮助避免合并冲突。
储存在单一文件内¶
Modelica语言源代码可以用数种方法映射到文件系统中。最简单的方法将所有信息存储为一个文件。此类文件会带有.mo后缀。这个文件可能只包含一个模型定义,也可能包含一个内有深层嵌套的包或任何两者之间的内容。
储存为文件夹¶
正如上述讨论,将一切存储在单个文件内通常不是一个好主意。另一种方法是Modelica语言定义映射到一个目录结构里。要将包储存为一个文件夹,可以通过创建一个与这个包名称相同的的文件夹以达成目的。然后,该目录内必须有一个名为package.mo
的文件存储此包内的定义,不过不包括任何嵌套定义 。嵌套定义可以存储为(如上文所述的)单个文件,或者(如在本段中描述般)作为目录形式 。下图试图以可视化形式描述一个文件夹布局的例子:
/RootPackage # Top-level package stored as a directory
package.mo # Indicates this directory is a package
NestedPackageAsFile.mo # Definitions stored in one file
/NestedPackageAsDir # Nested package stored as a directory
package.mo # Indicates this directory is a package
与名为RootPackage
的包关联的package.mo
文件将有类似如下的形式:
within;
package RootPackage
// only annotations can be stored in a package.mo
end RootPackage;
这里要注意两点。首先,这里没有本应存在的within
子句。这表明该包不在任何其它的包内。再者,NestedPackageAsFile
和NestedPackageAsDir
的定义并没有(也不能)出现。两者必须存储在package.mo
文件之外。
同样,与名为NestedPackageAsDir
的包关联的package.mo
文件如下:
within RootPackage;
package NestedPackageAsDir
// only annotations can be stored in a package.mo
end NestedPackageAsDir;
再一次,此包没有包含任何定义,只有标注。within
子句则略有不同,以反映NestedPackageAsDir
属于RootPackage
包这一事实。
最后,NestedPackageAsFile.mo
文件看起来会是这样的:
within RootPackage;
package NestedPackageAsFile
// The following can be stored here including:
// * constants
// * nested definitions
// * annotations
end NestedPackageAsFile;
这里的within
子句和NestedPackageAsDir
的包内的一致。不过,由于我们将本包存为单独的文件,常量、模型、包、函数等的嵌套定义均是允许的。
文件夹内的排序¶
若所有定义被存储在单个文件内,那么定义出现在文件中出现的顺序就是其在可视化环境(例如包浏览器)内的顺序。但是,若定义被存储在文件系统中,上述隐含的顺序便不存在。出于这个原因,开发者可以在package.mo旁边加入一个可选的package.order
文件以指定定义的顺序。该文件不过是包内嵌套的实体名称一行一个地组成的列表。因此,例如我们要为示例包结构加上顺序,那么文件系统将有如下内容:
/RootPackage # Top-level package stored as a directory
package.mo # Indicates this directory is a package
package.order # Specifies an ordering for this package
NestedPackageAsFile.mo # Definitions stored in one file
/NestedPackageAsDir # Nested package stored as a directory
package.mo # Indicates this directory is a package
package.order # Specifies an ordering for this package
若没有package.order
文件,Modelica语言工具很可能会简单地按字母顺序对包的内容进行排序。但如果我们想将RootPackage
的内容按字母顺序逆向排序,那么RootPackage
文件夹内的package.order
文件将如下所示:
NestedPackageAsFile
NestedPackageAsDir
这将告诉Modelica工具NestedPackageAsFile
应该排在NestedPackageAsDir
之前。
版本¶
MODELICAPATH
¶
多数Modelica工具允许用户通过指定文件的完整路径,或通过使用文件选择对话框打开文件。但每次查找打开大量文件并不十分有趣。出于这个原因,Modelica规范定义了名为MODELICAPATH
的特殊环境变量。用户可以用此变量来帮助工具自动地定位源代码的位置。
MODELICAPATH
环境变量包含了应搜索目录的列表。在Windows中,该列表的分隔符为;
,而在Unix中则为:
。当Modelica编译器遇到一个尚未读取的包时,编译器会从MODELICAPATH
环境变量的给定目录里搜索寻找匹配的文件或文件夹。例如,若MODELICAPATH
定义如下(假设我们使用Unix惯例):
/home/mtiller/Dir1:/home/mtiller/Dir2
而编译器在寻找一个名为MyLib
的包。那么编译器会首先在/home/mtiller/Dir1
内寻找名为MyLib.mo
的(作为单个文件存储的)包,或者一个名为MyLib
且内含package.mo
文件的文件夹。如果两者都没有出现,那么编译器会继而在/home/mtiller/Dir1
内(对相同的内容)进行查找。
modelica://
URL地址¶
在许多情况下,我们需要在Modelica包内包含非Modelica文件。这些非Modelica的文件可能包括数据、脚本、图像等。我们将这些非Modelica的文件称为“资源(resource)”。现在,我们已经介绍了Modelica定义是如何映射到文件系统中的。因此,我们可以讨论Modelica的一个非常有用的功能,即利用URL地址来指代资源的位置。
例如,当我们讨论外部函数时,我们引入了数个标注来指定资源的位置。具体而言,IncludeDirectory
和LibraryDirectory
标注分别指定了Modelica编译器寻找文件和库文件的位置。正如之前简要地提到的一样,上述标注的默认值以modelica:://LibraryName/Resources
开始。这样的URL地址允许我们相对于一个给定Modelica定义所在文件系统上的位置 定义资源的位置。让我们重新考虑前述的目录结构,不过这次我们增加了一些资源文件:
/RootPackage # Top-level package stored as a directory
package.mo # Indicates this directory is a package
package.order # Specifies an ordering for this package
NestedPackageAsFile.mo # Definitions stored in one file
/NestedPackageAsDir # Nested package stored as a directory
package.mo # Indicates this directory is a package
package.order # Specifies an ordering for this package
datafile.mat # Data specific to this package
/Resources # Resources are stored here by convention
logo.jpg # An image file
如果我们有模型需要包含在NestedPackageAsDir
内的数据文件,我们可以使用下面的URL来引用这个文件:
modelica://RootPackage/NestedPackageAsDir/datafile.mat
这样的URL地址以modelica://
开始。这表示我们所引用的资源相对于一个Modelica模型所在的位置。请不要将其错误理解为,例如说,一个通过网络获取的文件。在//
后面接着是Modelica定义的完全限定名,唯一的不同只是组件之间是由一个.
分隔开的,而是用/
。Modelica编译器会将其解释为包含该定义的文件夹名称。最后,URL的最末元素确定要使用文件的名称。
在另一个例子里,如果要引用Resources
包中的logo.jpg
文件,我们会使用如下URL:
modelica://RootPackage/Resources/logo.jpg
对于模型库的相关文件,常用惯例是将其存储在名为Resources
的子包内(因此IncludeDirectory
和LibraryDirectory
有上述默认值)。