Unmanaged code DLL created by TMC from MATLAB code for using in C#/.NET

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: