Example: calling a DLL generated with TMC from MATLAB source from Delphi application
The presented example demonstrates how to create a DLL from MATLAB sources (m-files) by means of TMC and call its exported functions from Delphi application code.
In the following example DLL function calculates points of a graph that is plotted by Delphi application. The DLL exported function is generated from m-code automatically and is called directly from Pascal.
The fragment of Delphi code:
/// File: nicplot.pas
unit nicplot;
interface
uses
...
TmcLib32; (* type definitions for calling function parameters *)
implementation
{$R *.fmx}
{ TMainForm }
(* External procedures from TMC Dll: *)
(* C-interface generated by TMC is
void tmcTestO(int nargout, int nargin,tmsMatrix *F,tmsMatrix *Mag,tmsMatrix *Ph,
tmsMatrix *f1,tmsMatrix *d1,tmsMatrix *f2,tmsMatrix *d2,tmsMatrix *NumFreqs,
tmsMatrix *Fmin__input__tmc,tmsMatrix *Fmax__input__tmc,tmsMatrix *Nint__input__tmc) ;
*)
procedure tmcTestO( nargout,nargin:Integer;F,Mag,Ph,f1,d1,f2,d2,NumFreqs,
Fmin,Fmax,NumInt:PTmcMatrix); cdecl; external 'SIMOR.dll';
...
(* calculate arrays F,Mag,Ph for given parameters w1,d1,w2,d2 *)
(* This function is called on change of these parameters that are entered from the form *)
procedure TMainForm.myFiltFreqResp(w1,d1,w2,d2:Double;NumFreqs:Integer;
var F,Mag,Ph: array of Double; Fmin,Fmax: Double; NumInt:Integer);
var
nargout,nargin:Integer;
(* variables passed to DLL. Type PTmcMatrix is declared in unit TmcLib32 *)
mF,mMag,mPh,mf1,md1,mf2,md2,mNumFreqs,mFmin,mFmax,mNumInt:PTmcMatrix;
actNumFreqs,k: Integer;
begin
nargout:=3;nargin:=8;
(* construct input variables *)
mF := __tmcNewMatrix;
mMag:= __tmcNewMatrix();
mPh:= __tmcNewMatrix();
mf1:= __tmcNewMatrix();
md1:= __tmcNewMatrix();
mf2:= __tmcNewMatrix();
md2:= __tmcNewMatrix();
mNumFreqs:= __tmcNewMatrix();
mFmin:= __tmcNewMatrix();
mFmax:= __tmcNewMatrix();
mNumInt:= __tmcNewMatrix();
tmcScalar(mf1,w1);
tmcScalar(md1,d1);
tmcScalar(mf2,w2);
tmcScalar(md2,d2);
tmcScalar(mNumFreqs,NumFreqs);
tmcScalar(mFmin,Fmin);
tmcScalar(mFmax,Fmax);
tmcScalar(mNumInt,NumInt);
tmcTestO( nargout,nargin,mF,mMag,mPh, // outputs
mf1,md1,mf2,md2,mNumFreqs, mFmin,mFmax,mNumInt // inputs
);
(* copy outputs: *)
actNumFreqs := tmcNumElem ( mF );
if NumFreqs < actNumFreqs then
actNumFreqs:= NumFreqs;
for k:=0 to actNumFreqs-1 do
begin
F[k] := mF^.complx.rData[k];
Mag[k] := mMag^.complx.rData[k];
Ph[k] := mPh^.complx.rData[k];
end;
(* destruct the input variables *)
tmcFreeLocalVar(mNumInt);
tmcFreeLocalVar(mFmax);
tmcFreeLocalVar(mFmin);
tmcFreeLocalVar(mNumFreqs);
tmcFreeLocalVar(md2);
tmcFreeLocalVar(mf2);
tmcFreeLocalVar(md1);
tmcFreeLocalVar(mf1);
tmcFreeLocalVar(mPh);
tmcFreeLocalVar(mMag);
tmcFreeLocalVar(mF);
end;
...
--------------------------------------
/// File: TmcLib32.pas
(* Interface for TMC run-time *)
unit TmcLib32;
interface
type
(* C-code:
struct tag_tmcMatrixDecriptor
{
enum MATRIX_TYPES m_type;
unsigned short m_modifier;
long m_nRows;// first dimension size
long m_nCols;// multiplication of all other dimensions
long *m_dims;// array of all dimentions of muli-dim matrix only
};
struct tag_tmsMatrix
{
// data is stored by columns
struct tag_tmcMatrixDecriptor m_desc;// matrix type and dimensions
union tag_val {
struct tagStructDef StructDef;
struct tagReIm complx;
struct tag_tmsMatrix **m_cells; // cells data (array of cells)
void (*fnc_ptr)(long,long,...);
double scalar_val; // value
struct tagForStruct ForStruct;
STRINGCODE hcode_val; // string code
} value;
};
*)
tmcMatrixDecriptor = record
m_type : Integer;
m_modifier : ShortInt;
m_nRows : Integer; // first dimension size
m_nCols : Integer; // multiplication of all other dimensions
m_dims : ^Integer; // array of all dimensions of multi-dim matrix only
end;
tagReIm = record
rData: array of Double;
iData: array of Double;
end;
(* type for output matrix. So far only numeric array is supported *)
TmcMatrix = record
m_desc : tmcMatrixDecriptor;
align1 : Integer;
complx : tagReIm;
end;
PTmcMatrix = ^TmcMatrix;
(* exported functions *)
function __tmcNewMatrix: PTmcMatrix;cdecl; external 'tmcrtvc8.dll';
procedure tmcScalar(dest:PTmcMatrix;x:Double);cdecl; external 'tmcrtvc8.dll';
procedure tmcFreeLocalVar(src:PTmcMatrix) ;cdecl; external 'tmcrtvc8.dll';
function tmcNumElem(x:PTmcMatrix):Integer;cdecl; external 'tmcrtvc8.dll';
implementation
end.
TMC DLL code
For more details refer to examples folder of TMC distribution.
/// DLL initialization code
#include <windows.h>
#include "tmc.h"
extern const struct CInit_funcs_table Init_funcs_table ;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
tmcInitLib(&Init_funcs_table);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
tmcFreeLib();
break;
}
return TRUE;
}
///====================================
% File: TestO.m
function [F,Mag,Ph]=TestO(f1,d1,f2,d2, NumFreqs,Fmin,Fmax,Nint)
% Calculate 2nd-order filter frequency response
if NumFreqs <2 || f1<= 0 || f2 <=0
F=0; Mag=0; Ph=0;
return;
end
if nargin <6
Fmin = min(f1,f2)*0.2;
Fmax = max(f1,f2)/0.2;
end
if (nargin <8)
Nint=0;
end
F = logspace( log10(Fmin),log10(Fmax), NumFreqs );
w1 = f1*2*pi; w2 = f2*2*pi;
w = F * 2*pi;
[Mag,Ph,num,den]=resp2nd(w1,d1,w2,d2,w);
[Mag2,Ph2,num2,den2]=respint(Nint,w);
Mag = Mag+Mag2;
Ph = Ph + Ph2;
num=conv(num,num2);
den=conv(den,den2);
% For debugging:
save('result.mat','Mag','Ph','num','den','w1','w2','d1','d2','w','NumFreqs','Fmin','Fmax','F');
%============================================
% File: resp2nd.m
function [Mag,Ph,num,den]=resp2nd(w1,d1,w2,d2,w)
% calculate response of second-order filter
s = j*w;
P = (s.^2 + 2 * d1 * w1 * s + w1 ^ 2) ./ (s.^2 + 2 * d2 * w2 * s + w2 ^ 2 ) * (w2/w1)^2 ;
Mag = 20* log10(abs(P));
Ph = unwrap( angle( P ) ) /pi * 180;
num = [1, 2 * d1 * w1, w1^2] / w1^2;
den = [1, 2 * d2 * w2, w2^2] / w2^2;
%File: respint.m
function [Mag,Ph,num,den]=respint(Ni,w)
% calculate response of integrators
s = j*w;
P = 1./ (s.^Ni); % TODO: Ni must be integer
Mag = 20*log10(abs(P));
Ph = unwrap( angle( P ) ) /pi * 180;
num = 1;
den = [1,zeros(1,Ni)];
%============================================
No comments:
Post a Comment