外部函数:C脚本中的引用头到已编译的dll

时间:2016-12-15 14:03:53

标签: modelica dymola

使用Dymola 2017。

案例A)调用外部c脚本

我成功实现了没有“#include< - >”语句的简单外部c函数:

Modelica功能:

function chirp

  input Modelica.SIunits.AngularVelocity w_start;
  input Modelica.SIunits.AngularVelocity w_end;
  input Real A;
  input Real M;
  input Real t;
  output Real u "output signal";

  external "C" u=chirp(w_start,w_end,A,M,t)
    annotation(IncludeDirectory="modelica://ExternalFuncTest/Resources/Source/", Include="#include \"chirp.c\"");

end chirp;

C-脚本:

double chirp(double w1, double w2, double A, double M, double time)
{
  double res;
  res=A*cos(w1*time+(w2-w1)*time*time/(2*M));

  return res;
}

案例B)在.dll文件中调用外部函数

我在编译的dll中调用外部函数也取得了成功:

Modelica功能:

function bessel_Jn
  "Bessel function of the 1st kind (regular cylindrical) of order n"

  extends Modelica.Icons.Function;

  input Integer n;
  input Real x;
  output Real y;

  external "C" y=gsl_sf_bessel_Jn(n,x) annotation(LibraryDirectory="modelica://ExternalFuncTest/Resources/Source/gsl-1.8/", Library="libgsl");

end bessel_Jn;

案例C)调用外部c脚本,该脚本通过标题使用外部.dll中的函数

我现在要做的是创建一个可以完成更多有趣事情的c函数。我目前的方法是在引用已编译的dll的c函数中包含头文件(在本例中是GNU科学库的编译版本)。这个例子有标题(虽然它目前没有做任何事情)。

Modelica功能:

function chirp

  input Modelica.SIunits.AngularVelocity w_start;
  input Modelica.SIunits.AngularVelocity w_end;
  input Real A;
  input Real M;
  input Real t;
  output Real u "output signal";

  external "C" u=chirp(w_start,w_end,A,M,t)
    annotation(LibraryDirectory="modelica://ExternalFuncTest/Resources/Source/gsl-1.8/", Library="libgsl",
               IncludeDirectory="modelica://ExternalFuncTest/Resources/Source/", Include="#include \"chirp.c\"");

end chirp;

C-CRIPT:

#include <gsl/gsl_sf_bessel.h> //<-- note the additional header

double chirp(double w1, double w2, double A, double M, double time)
{
  double res;
  res=A*cos(w1*time+(w2-w1)*time*time/(2*M));
  return res;
}

当尝试调用上面的函数时,由于头文件的存在,错误表示无法翻译而没有其他内容。如果头文件被注释掉,该函数将按预期运行。

如果您对如何正确实施此功能有任何见解,请与我们联系。谢谢。

供参考:下图是外部c脚本和.dll的路径。

路径错误:注意gsl header文件夹位于gsl-1.8文件夹中 Resources Source Folder

正确路径:注意gsl header文件夹与gsl-1.8文件夹处于同一级别 Corrected Resources Source Folder

UPDATE:标题有效,但函数调用导致转换失败

我已经更新了c脚本,现在调用一个应该被标题处理的函数。在目前的状态下,它不会起作用。也许它找不到.dll文件虽然它在modelica代码中指定了?我是否必须在c脚本中包含load .dll命令?

#include <gsl/gsl_sf_bessel.h>

double chirp(double w1, double w2, double A, double M, double time)
{
  double res;
  double y;
  res=A*cos(w1*time+(w2-w1)*time*time/(2*M));
  y = gsl_sf_bessel_j0(time); // <-- Calls a function from the .dll file using the header
  return res;
}

3 个答案:

答案 0 :(得分:2)

我认为这只能通过实现未来Modelica语言规范3.4的相对包含路径或未来工具来解决。有关Modelica语言规范的相应更新,请参阅https://trac.modelica.org/Modelica/ticket/2103

答案 1 :(得分:2)

您将包含目录设置为modelica://ExternalFuncTest/Resources/Source/gsl-1.8/ 然后使用#include <gsl-1.8/gsl/gsl_errno.h>

你真的在目录gsl-1.8中有一个目录gsl-1.8(有些项目有这样的结构 - 但它通常很少见)?如果不是这种情况则更改为#include <gsl/gsl_errno.h>

我相信在路径中也会搜索分层包含,因此应该可行;否则,您始终可以将includeDirectory设置为modelica://ExternalFuncTest/Resources/Source/gsl-1.8/gsl并使用#include <gsl_errno.h>

答案 2 :(得分:2)

可以从由Modelica外部函数调用调用的c脚本引用编译库头。

但是,仍然无法确定是否有一种有效的方法来访问.dll。这在后续问题External Functions: Alternative Method to use .dll from a C-script中进行了讨论。

提供了允许识别头文件的解决方案。感谢所有回应帮助解决这个问题的人。

步骤1)创建文件夹结构

Modelica会自动查找默认目录以获取外部函数依赖项。 modelica.org/documents/ModelicaSpec33Revision1.pdf

的第12.9.4节

Modelica查找已编译库的默认位置是项目的Resources文件夹中名为Library的文件夹:

LibraryDirectory="modelica://LibraryPackageName/Resources/Library"

对于头文件和c脚本,默认位置是项目的Resources文件夹中名为Include的文件夹:

IncludeDirectory="modelica://LibraryPackageName/Resources/Include"

要指定备用目录,请遵循modelica规范文档。从Modelica规范3.3版本1开始,您只能指定一个LibraryDirectory和一个IncludeDirectory。虽然这可以在将来解决https://trac.modelica.org/Modelica/ticket/2103

整体文件夹结构摘要 Required Folder Structure

步骤2)在上图中指定的位置创建Modelica函数和C脚本

以下是可供参考的示例。

Modelica功能

function chirp

  input Modelica.SIunits.AngularVelocity w_start;
  input Modelica.SIunits.AngularVelocity w_end;
  input Real A;
  input Real M;
  input Real t;
  output Real u "output signal";

  external "C" u=chirp(w_start,w_end,A,M,t)
    annotation(Library="libgsl",Include="#include \"chirp.c\"");

end chirp;

C脚本

#include <gsl/gsl_sf_bessel.h>

double chirp(double w1, double w2, double A, double M, double time)
{
  double res;
  res=A*cos(w1*time+(w2-w1)*time*time/(2*M));
  return res;
}