外部函数:将 C 脚本中的头文件引用到已编译的 dll [英] External Functions: Reference headers in C-script to compiled dll

查看:31
本文介绍了外部函数:将 C 脚本中的头文件引用到已编译的 dll的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Dymola 2017.

案例 A) 调用外部 c 脚本

我已经成功实现了没有#include <-->"的简单外部c函数声明:

Modelica 函数:

功能啁啾输入 Modelica.SIunits.AngularVelocity w_start;输入 Modelica.SIunits.AngularVelocity w_end;输入实数A;输入实数 M;输入实数 t;output Real u输出信号";外部C"u=chirp(w_start,w_end,A,M,t)annotation(IncludeDirectory="modelica://ExternalFuncTest/Resources/Source/", Include="#include \"chirp.c\"");结束啁啾;

C 脚本:

double chirp(double w1, double w2, double A, double M, double time){双水库;res=A*cos(w1*time+(w2-w1)*time*time/(2*M));返回资源;}


情况 B) 在 .dll 文件中调用外部函数

我也成功地在编译后的 dll 中调用外部函数:

Modelica 函数:

函数 bessel_Jnn阶第一类(正圆柱)贝塞尔函数"扩展 Modelica.Icons.Function;输入整数 n;输入实数 x;输出实数 y;外部C"y=gsl_sf_bessel_Jn(n,x) 注释(LibraryDirectory=modelica://ExternalFuncTest/Resources/Source/gsl-1.8/",Library=libgsl");结束 bessel_Jn;


Case C) 调用外部 c 脚本,该脚本通过标头使用来自外部 .dll 的函数

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

Modelica 函数:

功能啁啾输入 Modelica.SIunits.AngularVelocity w_start;输入 Modelica.SIunits.AngularVelocity w_end;输入实数A;输入实数 M;输入实数 t;output Real u输出信号";外部C"u=啁啾(w_start,w_end,A,M,t)注释(LibraryDirectory=modelica://ExternalFuncTest/Resources/Source/gsl-1.8/",Library=libgsl",IncludeDirectory="modelica://ExternalFuncTest/Resources/Source/", Include="#include \"chirp.c\"");结束啁啾;

C 脚本:

#include //<-- 注意附加的标题双啁啾(双w1,双w2,双A,双M,双时间){双水库;res=A*cos(w1*time+(w2-w1)*time*time/(2*M));返回资源;}

当尝试调用上面的函数时,错误表明无法翻译,并且由于头文件的存在没有其他原因.如果头文件被注释掉,该函数将按预期运行.

如果您对如何正确实施此功能有任何见解,请告诉我.谢谢.


供参考:下图是外部c-script和.dll的路径.

错误的路径:注意 gsl 头文件夹在 gsl-1.8 文件夹中

正确路径:注意 gsl 头文件夹与 gsl-1.8 文件夹在同一级别


更新:标题有效,但函数调用导致翻译失败

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

#include 双啁啾(双w1,双w2,双A,双M,双时间){双水库;双y;res=A*cos(w1*time+(w2-w1)*time*time/(2*M));y = gsl_sf_bessel_j0(时间);//<-- 使用标头从 .dll 文件调用函数返回资源;}

解决方案

可以从由 Modelica 外部函数调用调用的 c 脚本中引用已编译的库头文件.

但是,目前还没有确定是否有访问.dll的有效方法.这在后续问题

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

以下示例可供参考.

Modelica 函数

功能啁啾输入 Modelica.SIunits.AngularVelocity w_start;输入 Modelica.SIunits.AngularVelocity w_end;输入实数A;输入实数 M;输入实数 t;output Real u "输出信号";外部C"u=chirp(w_start,w_end,A,M,t)annotation(Library="libgsl",Include="#include \"chirp.c\"");结束啁啾;

C 脚本

#include 双啁啾(双w1,双w2,双A,双M,双时间){双水库;res=A*cos(w1*time+(w2-w1)*time*time/(2*M));返回资源;}

Using Dymola 2017.

Case A) Calling an external c-script

I have had success implementing simple external c functions that have no "# include <-->" statements:

Modelica Function:

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-script:

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;
}


Case B) Calling an external function in a .dll file

I also have had success in calling external functions within a compiled dll:

Modelica Function:

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;


Case C) Calling an external c-script which uses functions from an external .dll via headers

What I want to do now is create a c function that does more interesting things. My current approach is to include header files in the c function that references the compiled dll (in this case a compiled version of the GNU scientific library). This example has the header (although it does not do anything for the moment).

Modelica Function:

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;
}

When attempting to call the function above the error indicates failure to translate and nothing else due to the existence of the header file. If the header file is commented out the function will run as expected.

Please let me know if you have any insight as to how to properly go about implementing this feature. Thank you.


For reference: The image below is the path to the external c-script and .dll.

Wrong Path: Note gsl header folder is within gsl-1.8 folder

Correct Path: Note gsl header folder is at the same level as gsl-1.8 folder


UPDATE: Header works but function call causes translation to fail

I have updated the c-script to now call a function that should be handeled by the header. In its current state it won't work. Perhaps it can't find the .dll file although its specified in the modelica code? Do I have to include a load .dll command in the c-scripts?

#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;
}

解决方案

Referencing compiled library headers from c-scripts that are called by a Modelica external function call is possible.

However, it is still not determined if there is an efficient method to access the .dll. This is discussed in a follow up question External Functions: Alternative Method to use .dll from a C-script.

The solution that allowed the header files to be recognized is presented. Thanks to all who responded in helping figure this out.


Step 1) Create Folder Structure

Modelica looks in default directories automatically for external function dependencies. Section 12.9.4 of modelica.org/documents/ModelicaSpec33Revision1.pdf

The default location that Modelica looks for compiled libraries is a folder called Library within the Resources folder of your project:

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

For header files and c-scripts the default location is a folder called Include within the Resources folder of your project:

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

To specify alternative directories follow the modelica spec document. As of Modelica Specification 3.3 Rev 1 you can only specify one LibraryDirectory and one IncludeDirectory. Though this may be addressed in the future https://trac.modelica.org/Modelica/ticket/2103.

Summary of Overall Folder Structure

Step 2) Create Modelica Function and C-Scripts in locations specified in above image

Below are examples that can be used for reference.

Modelica Function

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-Script

#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;
}

这篇关于外部函数:将 C 脚本中的头文件引用到已编译的 dll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆