一、前期准备
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。
双击第一行蓝字体 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中,这样就可以同时显示两张图
//延时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 运行结果
一次运行时间比较长,需耐心等待一下:
**
三、参考文献**
感谢博主的分享: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