Внешние функции и процедуры

Top  Previous  Next

Внешняя функция или процедура – это подпрограмма, реализованная вне AnyDynamics с использованием сторонних инструментальных средств

(C#, Delphi, Fortran и т.д.).  Использование внешних процедур и функций показано в демо-примере "ExtFun".

 

В качестве определения внешней функции или процедуры в классе или пакете указывается только спецификация подпрограммы.

Реализация внешней функции или процедуры должна находиться в динамической библиотеке (DLL), которую необходимо

поместить в папку модели.

 

Функция, реализующая внешнюю функцию или процедуру, должна экспортироваться из DLL и иметь тип вызова stdcall.

Формальные параметры должны соответствовать внутреннему представлению типов формальных параметров в определении внешней функции

или процедуры (см. ниже). Параметры вида out и in out а также матрицы, записи и массивы в реализующей функции должны передаваться по адресу.

 

Пример определения внешней функции:

 

public function xlim(in x: double; in a: double) return double is external "ExampleDll.dll";  -- Ada

 

public extern double xlim(double x, double a)  "ExampleDll.dll"; -- C#

 

Внутреннее представление скалярных типов:

 

для модельного типа double используется программный тип "64-разрядное вещественное число" (double для Pascal и C#);

для модельных типов integer, byte, short используется программный тип "32-разрядное целое" (integer для Pascal, int для C#);

для модельного типа boolean используются программные типы boolean для Pascal и bool для C#;

для модельных типов string, char используются программные типы widestring для Pascal и string для C#;

для перечислимых типов используется целое число – номер перечислимого литерала, отсчитываемый от нуля.

 

Внутреннее представление векторов и матриц:

 

Значения матриц и векторов представляются двумерными вариантными массивами размерности 1..N, 1..M с элементами типа double.

Для векторов M=1.

 

Pascal

 

Для получения значения элемента [i,j] из внутреннего представления значения матрицы используйте индексацию:

 

var MX: variant;

var x: double;

...

x:=MX[i,j];

 

Для создания внутреннего представления матрицы размерности [N,M] используйте функцию VarArrayCreate:

 

MX:=VarArrayCreate([1,N,1,M],varDouble);

..

MX[1,3]:=2.87;

..

 

C#

 

Для получения значения элемента [i,j] из внутреннего представления значения матрицы используйте стандартный класс Array:

 

object MX;

double x;

..

x = (double)(MX as Array).GetValue(i,j);

 

Для создания внутреннего представления матрицы размерности [N,M] используйте метод CreateInstance:

 

int[] ss = {N, M};

int[] lb = {1,1};

MX = Array.CreateInstance(typeof(double), ss, lb);

(MX as Array).SetValue(2.87, 1, 3); // MX[1,3] == 2.87

 

 

Внутреннее представление записей:

 

Значения записей представляются двумерными вариантными массивами размерности 0..N-1, 0..1, где N – число компонентов записи, с элементами типа variant или object.

 

Элемент [i,0] содержит имя i-го компонента записи в 16-битном представлении. Элемент [i,1] содержит значение i-го компонента записи в представлении, соответствующем его типу.

 

Пусть

type TR is

record

 D: double;

 I: integer;

 B: boolean;

 S: string;

end record;

...

R: TR := {D=>0.3,I=>5,B=>true,S=>"ABC"};

 

Pascal

 

var R: variant;

var D: double;

var I: integer;

var B: boolean;

var S: widestring;

..

D:=R[0,1];

I:=R[1,1];

B:=R[2,1];

S:=R[3,1];

...

R:=VarArrayCreate([0,3,0,1],varVariant);

R[0,0]:="D"; R[0,1]:=D;

R[1,0]:="I"; R[1,1]:=I;

R[2,0]:="B"; R[2,1]:=B;

R[3,0]:="S"; R[3,1]:=S;

 

C#

 

object R;

double D;

int I;

bool B;

string S;

..

D = Convert.ToDouble((R as Array).GetValue(0,1));

I = Convert.ToInt32((R as Array).GetValue(1,1));

B = Convert.ToBoolean((R as Array).GetValue(2,1));

S = Convert.ToString((R as Array).GetValue(3,1));

...

int[] ss = { 4, 2 };

int[] lb = { 0, 0 };

R = Array.CreateInstance(typeof(object), ss, lb);

(R as Array).SetValue("D", 0, 0);

(R as Array).SetValue(D, 0, 1);

(R as Array).SetValue("I", 1, 0);

(R as Array).SetValue(I, 1, 1);

(R as Array).SetValue("B", 2, 0);

(R as Array).SetValue(B, 2, 1);

(R as Array).SetValue("S", 3, 0);

(R as Array).SetValue(S, 3, 1);

 

Внутреннее представление массивов:

 

Значения массивов представляются одномерными массивами размерности 0..N-1, где N – число элементов в массиве, с элементами типа variant или object.

I-й элемент вариантного массива содержит значение i-го элемента массива в модели в представлении, соответствующем его типу.

 

Пусть

 

AD: array of double;

AR: array of TR;

 

 

Pascal

 

var AD: variant;

var AR: variant;

var R: variant;

var D: double;

var I: integer;

...

D:=AD[2];

R:=AR[1];

I:=R[1,1];

..

AD:=VarArrayCreate([0,3],varVariant);

AR:=VarArrayCreate([0,3],varVariant);

..

AD[2]:=D;

AR[1]:=R;

 

C#

 

object AD;

object AR;

object R;

double D;

int I;

..

D = Convert.ToDouble((AD as Array).GetValue(2));

R = (AR as Array).GetValue(1);

I = Convert.ToInt32((R as Array).GetValue(1,1));

...

int[] ss = { 4 };

int[] lb = { 0 };

AD = Array.CreateInstance(typeof(object), ss, lb);

AR = Array.CreateInstance(typeof(object), ss, lb);

 

(AD as Array).SetValue(D, 2);

(AR as Array).SetValue(R, 1);