# 外部函数调用


在 Sysplorer 中,C/C++ 语言编译的外部函数定义方式主要有以下五种:

  • 使用 C 文件(例如.c.h文件),在 annotation 中用 Include 注解包含被调用函数实现的 C 文件;

  • 使用链接库文件(.lib文件),在 annotation 中用 Library 注解指定链接库,从而调用指定库中的函数。Sysplorer 既支持动态链接库(包含.lib.dll文件),也支持静态链接库(包含.lib文件);

  • 无外部文件,在 annotation 中用 Include 注解直接嵌入 C 代码;

  • Sysplorer 支持外部函数在环境变量中配置。

  • Sysplorer 提供了外部函数编辑器,使得用户能够以可视化的方式导入和编辑外部 C/C++ 函数

# 头文件

Modelica 中外部函数声明时用 Include 注解指定所需的.c文件(或.h文件)。IncludeDirectory 注解指定所需的.c文件(或.h文件)所在的位置。

调用的外部函数内容如下,该函数的目的是将输入值相加 。

  double add(double a , double b)
  {
	  return a + b;
  }

示例1:

model UriTest1
  //将外部函数封装成function
  function IncTest1
    input Real a1;
    input Real b1;
    output Real c1;
    //外部函数声明
    //IncludeDirectory注解指定包含文件所在的位置,以URI的modelica模式表示
    //Include指定外部函数所需的头文件
  external "C" c1 = add(a1, b1)
  annotation (IncludeDirectory = 
    "modelica://ExternFunc/Include", 
    Include = "#include\"add.c\"");
  end IncTest1;
  //调用函数IncTest1
  Real y = IncTest1(2.0, 3.0);
end UriTest1;

Include 注解:Include = "#include"add.c"" ,表示add.c为外部函数所需的头文件。

IncludeDirectory 注解:IncludeDirectory ="modelica://ExternFunc/Include" ,表示add.c位于 ExternFunc/Include 文件夹中。这里 IncludeDirectory 注解中.c文件所在路径采用了 Modelica 模式 URI 的方式来表示,关于 Modelica 模式 URI 的具体内容请参见外部资源说明。

# 链接库文件

Modelica 中外部函数声明时用 Library 注解指定链接库名(注意:不带扩展名)。LibraryDirectory 注解指定链接库文件和dll(或so)文件所在的位置。

示例2:

model TestExternFuncUseDll
  function call_lib
    input Real a;
    input Real b;
    output Real y;
    //Library指定链接库
    //LibraryDirectory指定库文件所在的位置
  external "C" y = add(a, b) 
  annotation (
    Library = "add", 
    LibraryDirectory = "modelica://ExternFunc/library");
  end call_lib;

  parameter Real a = 1;
  parameter Real b = 2;
  Real addr;
equation
  addr = call_lib(a, b);
end TestExternFuncUseDll;

上例中指定的链接库名是add,那么完整的链接库名称是add.lib(vc 编译生成)或Load.a(gcc 编译生成),指定的链接库文件和dll(或so)文件所在的位置是ExternFunc/library。此处 Sysplorer 求解器设置为“32 位求解器”。

LibraryDirectory 指定位置中可以使用不同的平台文件夹存放各平台的库文件和dll(或so)文件:

  • win32 [32 位 Microsoft Windows]

  • win64 [64 位 Microsoft Windows]

  • linux32 [Intel 32 位 Linux]

  • linux64 [Intel 64 位 Linux]

目前 Sysplorer 支持 win32 、win64 平台文件夹。如果没有平台文件夹,就位于指定目录中。如果文件夹 library 下同时存在 win32 和 win64 两个文件夹,则由求解器的位数决定在哪个文件夹中搜索文件。求解器的位数在 仿真设置 >编译 中设置。

Sysplorer 要求保持求解器和链接库文件的一致性,当求解器为 32 位时,相对的链接库文件在 vc 或 gcc 中编译时必须也由 32 位平台生成。

提示

  • 一般情况下要求同时具有 IncludeDirectory 注解和 LibraryDirectory 注解;
  • 要使模型仿真时能正确找到外部函数相关的资源文件,IncludeDirectory 注解和 LibraryDirectory 注解中指定的文件位置需要遵循 Modelica 模式 URI ,具体内容请参见外部资源

# 无外部文件

在没有外部文件(C文件或库文件)的情况下,可以直接将 C 代码嵌入到 Include 注解中。但是由于这种方式不适合调试,所以不建议使用。

示例3:

model UriTest2
  //将外部函数封装成function
  function IncTest2
    input Real x1;
    input Real x2;
    output Real y;
  //外部函数声明
  //Include引用外部函数的关键字
  //add(double x,double y){return x+y;} 外部函数的具体实现
  external "C" y = add(x1, x2)
  annotation (Include = 
    "double add(double x,double y)
  {
    return x+y;
  }");
  end IncTest2;
  //调用函数IncTest2
  Real y1 = IncTest2(1.0, 2.0);
end UriTest2;

对应如下的 C 函数原型:

double add(double x,double y);

翻译为 C 中的调用为:

y = add(1.0,2.0);

返回值 y=1.0+2.0=3.0。

# 头文件和库文件的默认搜索路径

如果没有 IncludeDirectory 注解,外部函数所需头文件默认位置是../Resources/Include。同样,若没有 LibraryDirectory 注解,外部函数所需库文件默认位置是../Resources/Library

下例中外部函数有 Include、Library 注解但没有 IncludeDirectory、LibraryDirectory 注解。

示例4:

package Functions
  function ExternalFunc1 "没有 LibraryDirectory 注解,调用该函数时搜索“Resources/Library”子文件"
    input Real x;
    output Real y;
  external "C" y = getreal_arg(x)
  annotation (Library = "ExternFunction");
  end ExternalFunc1;
  function ExternalFunc2 "没有 IncludeDirectory 注解,调用该函数时搜索“Resources/Include”子文件"
    input Real x;
    output Real y;
  external "C" y = getreal_arg(x)
  annotation (Include = "#include\"ExportFuncs2.c\"");
  end ExternalFunc2;
  function ExternalFunc3 "调用该函数时同时搜索“Resources/Library”、“Resources/Include”子文件"
    input Real x;
    output Real y;
  external "C" y = getreal_arg(x)
  annotation (Library = "ExternFunction",
    Include = "#include\"ExportFuncs.h\"");
  end ExternalFunc3;
end Functions;

那么,头文件和库文件的默认搜索路径如下所示: 图中 1 为定义 Modelica 外部函数的模型文件,2 为头文件搜索路径,3 为不同平台库文件搜索路径,4 为 vg 库文件,5为 gcc 库文件。