这是一个伴随问题外部函数:在 C 脚本中引用头文件来编译 dll.
该堆栈溢出问题是使用 Modelica 外部函数调用 c 脚本。然后,该 c 脚本使用 .dll 中包含的 c 函数。以下是我尝试过的最初首选方法和我不喜欢的工作尝试。
初步尝试:
以下代码将不起作用。我的假设是因为我加载了 .dll 库libgsl
在 Modelica 中,我可以简单地使用 C 脚本中的标头来使用来自该 .dll 的函数调用。但是,dslog.txt文件表明无法识别gsl_sf_bessel_j0
。显然,C 脚本不知道任何关于libgsl.dll
我在 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 chirp2(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(res);
return y;
}
工作尝试:
为了使用 C 脚本在外部函数调用中使用 .dll,我发现有必要使用LoadLibrary
命令。
这个方法真的有必要吗?这比我最初的尝试要复杂得多,我希望 Modelica 包含加载 .dll 所需的“诀窍”。
Bonus:似乎有一种方法可以将错误消息发送回 Modelica。void ModelicaVFormatError(const char* string, va_list)。了解其用法的参考示例,以便我可以替换似乎不会将任何内容发送回 Modelica 的 printf 语句?
模型功能:
function chirp
input Modelica.SIunits.AngularVelocity w_start;
input Modelica.SIunits.AngularVelocity w_end;
input Real A;
input Real M;
input Real t;
input String fileName= Modelica.Utilities.Files.loadResource("modelica://ExternalFuncTest/Resources/Library/libgsl.dll") "Full file name for GSL library";
output Real u "output signal";
external "C" u=chirp(w_start,w_end,A,M,t)
annotation(Include="#include \"chirp.c\""); // <-- Removed Library reference
end chirp;
C 脚本:
#include <windows.h>
#include <stdio.h>
typedef double (__cdecl *BESSEL)(const double);
double chirp3(double w1, double w2, double A, double M, double time, const char* fileName)
{
HINSTANCE hinstLib;
BESSEL bessel_J0;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
// Get a handle to the DLL module.
hinstLib = LoadLibrary(fileName);
// If the handle is valid, try to get the function address.
double res;
double y = 0;
res=A*cos(w1*time+(w2-w1)*time*time/(2*M));
if (hinstLib != NULL)
{
bessel_J0 = (BESSEL) GetProcAddress(hinstLib, "gsl_sf_bessel_j0");
// If the function address is valid, call the function.
if (NULL != bessel_J0)
{
fRunTimeLinkSuccess = TRUE;
printf("Success loading library method.\n"); //<-- Alternative to send message back to Modelica log file?
y = bessel_J0(res);
} else
{
printf("Failed to load library\n"); //<-- Alternative to send message back to Modelica log file?
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
return y;
}