Usage DLL from C#
Here is a C# code fragment that implements the DLL-wrapper class wizDll and calls its method calccurrentctrl./// File: dnicplotdll.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace NicPlotDll
{
class wizDll
{
[System.Runtime.InteropServices.DllImport("dll_getcurloop.dll", EntryPoint = "calccurrentctrl",
SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern void calccurrentctrl(
out double PropGain, out double IntGain, out UInt32 FreqLen, double[] FreqHz,
double [] OL_Mag,double [] OL_Ph,double [] CL_Mag,double [] CL_Ph,
out UInt32 RespLen, double[] RespTime, double[] Resp, UInt32 MaxFreqLen,
UInt32 MaxTimeLen, double R, double L, double Ts, double Ovs);
}
}
/// File: FormDesPI.cs
using NicPlotDll;
public class FormDesPI : Form
{
private double PropGain=0;
private double IntGain=0;
private UInt32 FreqLen=0;
private double [] FreqHz;
private double [] OL_Mag;
private double [] OL_Ph;
private double [] CL_Mag;
private double [] CL_Ph;
private UInt32 RespLen=0;
private double [] RespTime;
private double [] Resp;
private double R = 0.2;
private double L = 0.002;
private double Ts = 50e-6F;
private double Ovs = 1.15F;
private const UInt32 MaxFreqLen = 1000;
private const UInt32 MaxTimeLen = 60;
public FormDesPI()
{
FreqHz = new double[(int)MaxFreqLen];
OL_Mag = new double[(int)MaxFreqLen];
OL_Ph = new double[(int)MaxFreqLen];
CL_Mag = new double[(int)MaxFreqLen];
CL_Ph = new double[(int)MaxFreqLen];
RespTime=new double[(int)MaxTimeLen];
Resp = new double[(int)MaxTimeLen];
InitializeComponent();
this.textBoxR.Text = Convert.ToString(R);
this.textBoxL.Text = Convert.ToString(L);
this.textBoxOvs.Text = Convert.ToString(100*(Ovs-1));
initPlots();
}
private void buttonRun_Click(object sender, EventArgs e)
{
L=Convert.ToDouble(this.textBoxL.Text);
R = Convert.ToDouble(this.textBoxR.Text);
Ovs = 1+ 0.01*Convert.ToDouble(this.textBoxOvs.Text);
NicPlotDll.wizDll.calccurrentctrl(out PropGain,out IntGain,out FreqLen, FreqHz,
OL_Mag, OL_Ph, CL_Mag,CL_Ph,
out RespLen,RespTime,Resp, MaxFreqLen, MaxTimeLen, R, L, Ts, Ovs);
this.textBoxKi.Text = Convert.ToString(IntGain);
this.textBoxKp.Text = Convert.ToString(PropGain);
bodePlot.drawBode(FreqHz, CL_Mag, CL_Ph, FreqLen);
nicholsPlot.drawNichols(OL_Mag, OL_Ph, FreqLen);
StepRespPlot.drawStepResponse(RespTime, Resp, RespLen);
}
}
DLL code
Here is the manually written wrapper for the TMC-generated code:#include <windows.h>
#include "tmc.h"
void tmcTestO(int nargout, int nargin,tmsMatrix *PropGain,tmsMatrix *IntGain,tmsMatrix *FreqLen,tmsMatrix *FreqHz,tmsMatrix *OL_Mag,tmsMatrix *OL_Ph,tmsMatrix *CL_Mag,tmsMatrix *CL_Ph,tmsMatrix *RespLen,tmsMatrix *RespTime,tmsMatrix *Resp,
tmsMatrix *R,tmsMatrix *L,tmsMatrix *Ts,tmsMatrix *Ovs) ;
void __stdcall calccurrentctrl(double *PropGain,double *IntGain,long *FreqLen,double *FreqHz,
double *OL_Mag,double *OL_Ph,double *CL_Mag,double *CL_Ph,
long *RespLen,double *RespTime,double *Resp,long MaxFreqLen,long MaxTimeLen,double R,double L,double Ts,double Ovs)
{unsigned long k;
unsigned long len;
tmsMatrix *mPropGain = tmcNewMatrix();
tmsMatrix *mIntGain = tmcNewMatrix();
tmsMatrix *mFreqLen = tmcNewMatrix();
tmsMatrix *mFreqHz = tmcNewMatrix();
tmsMatrix *mOL_Mag = tmcNewMatrix();
tmsMatrix *mOL_Ph = tmcNewMatrix();
tmsMatrix *mCL_Mag = tmcNewMatrix();
tmsMatrix *mCL_Ph = tmcNewMatrix();
tmsMatrix *mRespLen = tmcNewMatrix();
tmsMatrix *mRespTime = tmcNewMatrix();
tmsMatrix *mResp = tmcNewMatrix();
tmsMatrix *mR = tmcNewMatrix();
tmsMatrix *mL = tmcNewMatrix();
tmsMatrix *mTs = tmcNewMatrix();
tmsMatrix *mOvs = tmcNewMatrix();
tmcScalar(mR,R);
tmcScalar(mL,L);
tmcScalar(mTs,Ts);
tmcScalar(mOvs,Ovs);
tmcTestO(11, 4, // nargout,nargin
mPropGain,mIntGain,mFreqLen,mFreqHz,mOL_Mag,mOL_Ph,mCL_Mag,mCL_Ph,mRespLen,mRespTime,mResp, // [outputs]
mR,mL,mTs,mOvs) ; // [inputs]
// copy outputs
len = tmcNumElem ( mFreqHz );if (MaxFreqLen < len)
{
len = MaxFreqLen;
}
*FreqLen = len;for (k=0;k<len;k++)
{
FreqHz[k]=mFreqHz->value.complx.rData[k];
OL_Mag[k]= mOL_Mag->value.complx.rData[k];
OL_Ph[k] = mOL_Ph->value.complx.rData[k];
CL_Mag[k]= mCL_Mag->value.complx.rData[k];
CL_Ph[k] = mCL_Ph->value.complx.rData[k];
}
len = tmcNumElem ( mRespTime );if (MaxTimeLen < len)
{
len = MaxTimeLen;
}
*RespLen = len;for (k=0;k<len;k++)
{
RespTime[k]=mRespTime->value.complx.rData[k];
Resp[k] =mResp->value.complx.rData[k];
}
PropGain[0]=mPropGain->value.complx.rData[0];
IntGain[0]=mIntGain->value.complx.rData[0];
tmcFreeLocalVar(mOvs);
tmcFreeLocalVar(mTs);
tmcFreeLocalVar(mL);
tmcFreeLocalVar(mR);
tmcFreeLocalVar(mResp);
tmcFreeLocalVar(mRespTime);
tmcFreeLocalVar(mRespLen);
tmcFreeLocalVar(mCL_Ph);
tmcFreeLocalVar(mCL_Mag);
tmcFreeLocalVar(mOL_Ph);
tmcFreeLocalVar(mOL_Mag);
tmcFreeLocalVar(mFreqHz);
tmcFreeLocalVar(mFreqLen);
tmcFreeLocalVar(mIntGain);
tmcFreeLocalVar(mPropGain);
}
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;
}
MATLAB code
/// File: TestO.m
function [PropGain,IntGain,FreqLen,FreqHz,OL_Mag,OL_Ph,CL_Mag,CL_Ph,RespLen,RespTime,Resp]=TestO(R,L,Ts,Ovs)
....
Remarks
The provided example demonstrates how to call the TMC-generated DLL from C#. Both DLL and C# projects may be included in a single MSVC solution. The generated .NET application is unsafe however since it used unmanaged code from the DLL.
I suggest that TMC Compiler and its run-time library may be extended in order to generate managed C# code directly from the MATLAB code. A special issue is independent LAPACK code translation to C# but it may be also realized. The only question is if this work is really important for users of TMC Compiler. Any feedback will be appreciated.
No comments:
Post a Comment