Внешние функции: Ссылка заголовков в C-скрипте на скомпилированную DLL

Использование Dymola 2017.

Случай А) Вызов внешнего c-скрипта

Я успешно реализовал простые внешние функции c, которые не имеют операторов "# include <->":

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

Случай Б) Вызов внешней функции в 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 (в данном случае это скомпилированная версия научной библиотеки 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 находится в папке gsl-1.8 Папка с ресурсами

Правильный путь: обратите внимание, что папка заголовка gsl находится на том же уровне, что и папка gsl-1.8. Папка с исправленными ресурсами


ОБНОВЛЕНИЕ: заголовок работает, но вызов функции приводит к сбою перевода

Я обновил c-скрипт, чтобы теперь вызывать функцию, которая должна обрабатываться заголовком. В его текущем состоянии это не будет работать. Возможно, он не может найти файл.dll, хотя он указан в коде modelica? Нужно ли включать команду.dll в c-скрипты?

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

3 ответа

Решение

Возможна ссылка на заголовки скомпилированной библиотеки из c-скриптов, которые вызываются вызовом внешней функции Modelica.

Однако до сих пор не определено, существует ли эффективный способ доступа к.dll. Это обсуждается в следующем вопросе. Внешние функции: альтернативный метод использования.dll из C-скрипта.

Представлено решение, позволяющее распознавать заголовочные файлы. Спасибо всем, кто откликнулся, помогая разобраться в этом.


Шаг 1) Создайте структуру папок

Modelica автоматически ищет в каталогах по умолчанию внешние зависимости функций. Раздел 12.9.4 https://modelica.org/documents/ModelicaSpec33Revision1.pdf

Местоположение по умолчанию, которое Modelica ищет скомпилированные библиотеки, - это папка с именем Library в папке "Ресурсы" вашего проекта:

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

Для заголовочных файлов и c-скриптов местоположением по умолчанию является папка с именем Include в папке "Ресурсы" вашего проекта:

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

Чтобы указать альтернативные каталоги, следуйте документу спецификации modelica. Начиная с спецификации Modelica 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;
}

Вы устанавливаете каталог включения на 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>,

Я считаю, что это может быть решено только с помощью относительных путей включения или будущих инструментов, которые реализуют будущую спецификацию языка Modelica 3.4. См. https://trac.modelica.org/Modelica/ticket/2103 для соответствующего обновления спецификации языка Modelica.

Другие вопросы по тегам