使用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文件夹中
正确路径:注意gsl header文件夹与gsl-1.8文件夹处于同一级别
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;
}
答案 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。
步骤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;
}