External Functions: Reference headers in C-script to compiled dll

倾然丶 夕夏残阳落幕 提交于 2019-12-20 02:01:18

问题


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

回答1:


I believe this can only be resolved with relative include paths or future tools that implement future Modelica Language Specification 3.4. See https://trac.modelica.org/Modelica/ticket/2103 for the corresponding update on the Modelica Language Specification.




回答2:


You set include directory to modelica://ExternalFuncTest/Resources/Source/gsl-1.8/ and then use #include <gsl-1.8/gsl/gsl_errno.h>

Do you really have a directory gsl-1.8 in the directory gsl-1.8 (some projects have such a structure - but it is generally rare)? If that is not the case change to #include <gsl/gsl_errno.h>.

I believe hierarchical includes are also searched in the path and thus that should work; otherwise you could always set includeDirectory to modelica://ExternalFuncTest/Resources/Source/gsl-1.8/gsl and use #include <gsl_errno.h>.




回答3:


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


来源:https://stackoverflow.com/questions/41166086/external-functions-reference-headers-in-c-script-to-compiled-dll

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!