外部函数:在 C-script 中引用 headers 到已编译的 dll
External Functions: Reference headers in C-script to compiled dll
使用 Dymola 2017。
案例 A) 调用外部 c-script
我成功实现了没有“#include <-->”语句的简单外部 C 函数:
模型函数:
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;
}
案例 B) 在 .dll 文件中调用外部函数
我也成功地在已编译的 dll 中调用外部函数:
模型函数:
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-script,它通过 headers
使用外部 .dll 中的函数
我现在想做的是创建一个 c 函数来做更多有趣的事情。我目前的方法是在引用编译后的 dll(在本例中是 GNU 科学库的编译版本)的 c 函数中包含 header 文件。这个例子有 header(尽管它暂时没有做任何事情)。
模型函数:
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;
}
当尝试调用上述函数时,错误指示翻译失败,并且由于 header 文件的存在而没有其他原因。如果 header 文件被注释掉,函数将按预期 运行。
如果您对如何正确实施此功能有任何见解,请告诉我。谢谢。
供参考:下图是外部c-script和.dll.
的路径
错误路径: 注意 gsl header 文件夹在 gsl-1.8 文件夹中
正确路径:注意gsl header文件夹与gsl-1.8文件夹同级
更新: Header 有效但函数调用导致翻译失败
我已将 c-script 更新为现在调用应由 header 处理的函数。在目前的状态下,它是行不通的。也许它找不到 .dll 文件,尽管它在 modelica 代码中指定?我是否必须在 c-script 中包含加载 .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;
}
我相信这只能通过相关包含路径或实现未来 Modelica 语言规范 3.4 的未来工具来解决。有关 Modelica 语言规范的相应更新,请参阅 https://trac.modelica.org/Modelica/ticket/2103。
您将包含目录设置为 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>
.
可以从 c-scripts 引用由 Modelica 外部函数调用调用的已编译库 header。
但是,目前还不确定是否有有效的方法来访问.dll。这在后续问题 External Functions: Alternative Method to use .dll from a C-script.
中进行了讨论
给出了允许识别header个文件的解决方案。感谢所有帮助解决这个问题的人。
步骤 1) 创建文件夹结构
Modelica 会自动在默认目录中查找外部函数依赖项。 modelica.org/documents/ModelicaSpec33Revision1.pdf
的第 12.9.4 节
Modelica 查找已编译库的默认位置是项目资源文件夹中名为 Library
的文件夹:
LibraryDirectory="modelica://LibraryPackageName/Resources/Library"
对于 header 文件和 c-scripts,默认位置是项目资源文件夹中名为 Include
的文件夹:
IncludeDirectory="modelica://LibraryPackageName/Resources/Include"
要指定替代目录,请遵循 modelica 规范文档。从 Modelica Specification 3.3 Rev 1 开始,您只能指定一个 LibraryDirectory
和一个 IncludeDirectory
。虽然这可能会在未来得到解决 https://trac.modelica.org/Modelica/ticket/2103.
步骤 2) 在上图中指定的位置创建 Modelica 函数和 C-Scripts
以下是可供参考的范例
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-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;
}
使用 Dymola 2017。
案例 A) 调用外部 c-script
我成功实现了没有“#include <-->”语句的简单外部 C 函数:
模型函数:
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;
}
案例 B) 在 .dll 文件中调用外部函数
我也成功地在已编译的 dll 中调用外部函数:
模型函数:
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-script,它通过 headers
使用外部 .dll 中的函数我现在想做的是创建一个 c 函数来做更多有趣的事情。我目前的方法是在引用编译后的 dll(在本例中是 GNU 科学库的编译版本)的 c 函数中包含 header 文件。这个例子有 header(尽管它暂时没有做任何事情)。
模型函数:
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;
}
当尝试调用上述函数时,错误指示翻译失败,并且由于 header 文件的存在而没有其他原因。如果 header 文件被注释掉,函数将按预期 运行。
如果您对如何正确实施此功能有任何见解,请告诉我。谢谢。
供参考:下图是外部c-script和.dll.
的路径错误路径: 注意 gsl header 文件夹在 gsl-1.8 文件夹中
正确路径:注意gsl header文件夹与gsl-1.8文件夹同级
更新: Header 有效但函数调用导致翻译失败
我已将 c-script 更新为现在调用应由 header 处理的函数。在目前的状态下,它是行不通的。也许它找不到 .dll 文件,尽管它在 modelica 代码中指定?我是否必须在 c-script 中包含加载 .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;
}
我相信这只能通过相关包含路径或实现未来 Modelica 语言规范 3.4 的未来工具来解决。有关 Modelica 语言规范的相应更新,请参阅 https://trac.modelica.org/Modelica/ticket/2103。
您将包含目录设置为 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>
.
可以从 c-scripts 引用由 Modelica 外部函数调用调用的已编译库 header。
但是,目前还不确定是否有有效的方法来访问.dll。这在后续问题 External Functions: Alternative Method to use .dll from a C-script.
中进行了讨论给出了允许识别header个文件的解决方案。感谢所有帮助解决这个问题的人。
步骤 1) 创建文件夹结构
Modelica 会自动在默认目录中查找外部函数依赖项。 modelica.org/documents/ModelicaSpec33Revision1.pdf
的第 12.9.4 节Modelica 查找已编译库的默认位置是项目资源文件夹中名为 Library
的文件夹:
LibraryDirectory="modelica://LibraryPackageName/Resources/Library"
对于 header 文件和 c-scripts,默认位置是项目资源文件夹中名为 Include
的文件夹:
IncludeDirectory="modelica://LibraryPackageName/Resources/Include"
要指定替代目录,请遵循 modelica 规范文档。从 Modelica Specification 3.3 Rev 1 开始,您只能指定一个 LibraryDirectory
和一个 IncludeDirectory
。虽然这可能会在未来得到解决 https://trac.modelica.org/Modelica/ticket/2103.
步骤 2) 在上图中指定的位置创建 Modelica 函数和 C-Scripts
以下是可供参考的范例
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-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;
}