C#调用Matlab生成的dll文件进行直接绘图操作示例

一、前期准备
1.生成可用的dll文件
C#与matlab的混合编程中,C#程序调用matlab生成的dll文件是必不可少的,利用matlab强大的数据处理能力和绘图能力,可以优化C#程序,使得程序编写更为简便。
1.1 function文件的编写
在这里使用一个网上可以查阅的matlab绘制椭圆的function函数为例,参考博客https://blog.csdn.net/biubiu_buaa/article/details/71081048,
matlab函数代码如下:

 function  myline = mymatlab(a,b,c,d,e,f)
    % 画一般椭圆:ax*x+bx*y+c*y*y+d*x+e*y = f
    delta = b^2-4*a*c;
    if delta >= 0
        warning('这不是一个椭圆')
        return;
    end
    x0 = (b*e-2*c*d)/delta;
    y0 = (b*d-2*a*e)/delta;
    r = a*x0^2 + b*x0*y0 +c*y0^2 + f;
    if r <= 0
        warning('这不是一个椭圆')
        return;
    end
    
    aa = sqrt(r/a); 
    bb = sqrt(-4*a*r/delta);
    t = linspace(0, 2*pi, 60);

1.2 dll文件的生成
在matlab命令运行窗口输入mbuild -setup;得到下图所示的提示:所使用matlab版本为2018b。C#调用Matlab生成的dll文件进行直接绘图操作示例_第1张图片
双击第一行蓝字体 mex -setup C++ -client MBUILD ;得到下图提示:
C#调用Matlab生成的dll文件进行直接绘图操作示例_第2张图片
再次输入deploytool;弹出下图所示的提示框:选择第三个Library Compiler;
C#调用Matlab生成的dll文件进行直接绘图操作示例_第3张图片
在Type中选择.NET.Assembly,在EXPORTED FUNCTION中添加需要编译的function文件,此处mymatlab.m为function文件保存的文件名。如第二个所示,点击package进行编译。
C#调用Matlab生成的dll文件进行直接绘图操作示例_第4张图片
在NameSpace处可以添加名称,可以修改Class Name名称,在此处为简便将NameSpace命名为MyMatlab,Class Name修改为myline;
C#调用Matlab生成的dll文件进行直接绘图操作示例_第5张图片
C#调用Matlab生成的dll文件进行直接绘图操作示例_第6张图片
编译后生成的文件中有三个文件夹,选取第二个文件夹for_redistribution_files_only中的MyMatlab.dll文件。

有的电脑安装的matlab没有完全破解,无法使用matlab的MCRinstall组件,请下载与自己matlab版本相匹配的文件并安装。

二、C#函数的编写与调试
2.1 核心代码如下所示:
API

 #region //Windows API
        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);//
        [DllImport("user32.dll")]
        public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool BRePaint);
    const int GWL_STYLE = -16;
    const int WS_CAPTION = 0x00C00000;
    const int WS_THICKFRAME = 0x00040000;
    const int WS_SYSMENU = 0X00080000;
    [DllImport("user32")]
    private static extern int GetWindowLong(System.IntPtr hwnd, int nIndex);
    [DllImport("user32")]

调用matlab生成dll文件核心程序:

void startload_run()
{
int count50ms = 0;
//实例化matlab对象
MyMatlab.myline t = new MyMatlab.myline();
t.mymatlab((MWArray)3,(MWArray)2,(MWArray)4,(MWArray)0,(MWArray)0,(MWArray)5);//外部函数输入

            //循环查找figure1窗体
            while (figure1 == IntPtr.Zero)
            {
                //查找matlab的Figure 1窗体
                figure1 = FindWindow("SunAwtFrame", "Figure 1");//??如果有两个figure是否可以写成
                //figure2=FindWindow("SunAwtFrame", "Figure 2");然后把figure2放到panel2中,这样就可以同时显示两张图
                //延时50ms
                Thread.Sleep(50);
                count50ms++;
                //20s超时设置
                if (count50ms >= 400)
                {
                    label1.Text = "matlab资源加载时间过长!";
                    return;
                }
            }

            //跨线程,用委托方式执行
            UpdateUI update = delegate
            {
                //隐藏标签
                label1.Visible = false;
                //设置matlab图像窗体的父窗体为panel
                SetParent(figure1, panel1.Handle);
                //获取窗体原来的风格
                var style = GetWindowLong(figure1, GWL_STYLE);
                //设置新风格,去掉标题,不能通过边框改变尺寸
                SetWindowLong(figure1, GWL_STYLE, style & ~WS_CAPTION & ~WS_THICKFRAME);
                //移动到panel里合适的位置并重绘
                MoveWindow(figure1, 0, 0, panel1.Width + 20, panel1.Height + 40, true);
                //调用显示窗体函数,隐藏再显示相当于刷新一下窗体
                //radiobutton按钮使能
                radioButton1.Enabled = true;
                //radioButton2.Enabled = true;
                //radioButton3.Enabled = true;
                //radioButton4.Enabled = true;
                //radioButton5.Enabled = true;
                //radioButton6.Enabled = true;              
            };
            panel1.Invoke(update);
            //再移动一次,防止显示错误
            Thread.Sleep(100);
            MoveWindow(figure1, 0, 0, panel1.Width + 20, panel1.Height + 40, true);
        }

2.2 运行结果
一次运行时间比较长,需耐心等待一下:
C#调用Matlab生成的dll文件进行直接绘图操作示例_第7张图片
**
三、参考文献**
感谢博主的分享:https://blog.csdn.net/yxy244/article/details/79305757**
四、2019.4.19日更新代码部分:

        public delegate void UpdateUI();//委托用于更新UI
        IntPtr figure1;//图像句柄
        private void Form1_Load(object sender, EventArgs e)
        {
     
        }
        int a = 0;int b = 0;int c = 0;int d = 0;int f = 0;int g = 0;//给startload_run传值

        void startload_run()
        {
            int count50ms = 0;                      
            myline t = new myline();
            t.mymatlab((MWArray)a, b, c, d, f, g);//外部函数输入
            //循环查找figure1窗体
            while (figure1 == IntPtr.Zero)
            {
                figure1 = FindWindow("SunAwtFrame", "Figure 1");//??如果有两个figure是否可以写成        
                Thread.Sleep(50);
                count50ms++;
                if (count50ms >= 400)
                {
                    label1.Text = "matlab资源加载时间过长!";
                    return;
                }
            }

            UpdateUI update = delegate//委托
            {
                label1.Visible = false;
                SetParent(figure1, panel1.Handle);
                var style = GetWindowLong(figure1, GWL_STYLE);
                SetWindowLong(figure1, GWL_STYLE, style & ~WS_CAPTION & ~WS_THICKFRAME);
                MoveWindow(figure1, 0, 0, panel1.Width + 20, panel1.Height + 40, true);                         
            };
            panel1.Invoke(update);
            Thread.Sleep(100);
            MoveWindow(figure1, 0, 0, panel1.Width + 20, panel1.Height + 40, true);
        }

        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            a = 3;
            b = 2;
            c = 4;
            d = 0;
            f = 0;
            g = 5;
            Thread startload;//新线程
            startload = new Thread(new ThreadStart(startload_run));//线程执行部分
            startload.Start();//开线程
        }

        private void radioButton2_CheckedChanged(object sender, EventArgs e)
        {
            a = 3;
            b = 2;
            c = 4;
            d = 0;
            f = 0;
            g = 4;
            Thread startload;//新线程
            startload = new Thread(new ThreadStart(startload_run));
            startload.Start();                     
        }

        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            MoveWindow(figure1, 0, 0, panel1.Width + 20, panel1.Height + 40, true);
        } 

四、资源
为自己保存资源(包括matlab文件+dll+C#全套码源):https://download.csdn.net/download/weixin_43311110/10971077

你可能感兴趣的:(C#调用Matlab生成的dll文件进行直接绘图操作示例)