一、前期准备
1.生成可用的dll文件
C#与matlab的混合编程中,C#程序调用matlab生成的dll文件是必不可少的,利用matlab强大的数据处理能力和绘图能力,可以优化C#程序,使得程序编写更为简便。
1.1 function文件的编写
在这里使用一个网上可以查阅的matlab绘制椭圆的function函数为例,参考博客/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 = fdelta = b^2-4*a*c;if delta >= 0warning('这不是一个椭圆')return;endx0 = (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 <= 0warning('这不是一个椭圆')return;endaa = sqrt(r/a); bb = sqrt(-4*a*r/delta);t = linspace(0, 2*pi, 60);
1.2 dll文件的生成
在matlab命令运行窗口输入mbuild -setup;得到下图所示的提示:所使用matlab版本为b。
双击第一行蓝字体 mex -setup C++ -client MBUILD ;得到下图提示:
再次输入deploytool;弹出下图所示的提示框:选择第三个Library Compiler;
在Type中选择.NET.Assembly,在EXPORTED FUNCTION中添加需要编译的function文件,此处mymatlab.m为function文件保存的文件名。如第二个所示,点击package进行编译。
在NameSpace处可以添加名称,可以修改Class Name名称,在此处为简便将NameSpace命名为MyMatlab,Class Name修改为myline;
编译后生成的文件中有三个文件夹,选取第二个文件夹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中,这样就可以同时显示两张图//延时50msThread.Sleep(50);count50ms++;//20s超时设置if (count50ms >= 400){label1.Text = "matlab资源加载时间过长!";return;}}//跨线程,用委托方式执行UpdateUI update = delegate{//隐藏标签label1.Visible = false;//设置matlab图像窗体的父窗体为panelSetParent(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 运行结果
一次运行时间比较长,需耐心等待一下:
**
三、参考文献**
感谢博主的分享:/yxy244/article/details/79305757**
四、.4.19日更新代码部分:
public delegate void UpdateUI();//委托用于更新UIIntPtr 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#全套码源):/download/weixin_43311110/10971077
码源获取方式:DaShang 1RMB , 私聊截图+邮箱地址(不赞同这个方式的,大家勿喷)