请教一下能人在VS中调用MATLAB绘制动态驻波

已经可以调用MATLAB,但可能代码有问题,MATLAB图像不出来,求能人赐教!

这是对vs的配置

img

img

这是C语言代码

#include "engine.h"
#include 
#include 
#include <string.h>
#include 

int main()
{
    Engine* ep;
    mxArray* t = NULL, * l = NULL, * x = NULL, * y_fwd = NULL, * y_bwd = NULL, * y_res = NULL;
    double* t_data, * l_data, * x_data;
    double amp_fwd, freq_fwd, wavelen_fwd, amp_bwd, freq_bwd, wavelen_bwd;
    int i, j, n;

    // 连接到 MATLAB 引擎
    if (!(ep = engOpen(NULL)))
    {
        fprintf(stderr, "无法连接到 MATLAB 引擎\n");
        return EXIT_FAILURE;
    }

    // 创建 t 向量
    t = mxCreateDoubleMatrix(1, 1001, mxREAL);
    t_data = mxGetPr(t);
    for (i = 0; i < 1001; i++)
    {
        t_data[i] = i * 0.1;
    }

    // 创建 l 向量
    l = mxCreateDoubleScalar(10);
    l_data = mxGetPr(l);

    // 创建 x 向量
    x = mxCreateDoubleMatrix(1, 101, mxREAL);
    x_data = mxGetPr(x);
    for (i = 0; i < 101; i++)
    {
        x_data[i] = i * (*l_data) / 200;
    }

    // 获取用户输入参数
    printf("请输入正向波的振幅:\n");
    scanf("%lf", &_fwd);
    printf("请输入正向波的频率:\n");
    scanf("%lf", &freq_fwd);
    printf("请输入正向波的波长:\n");
    scanf("%lf", &wavelen_fwd);
    printf("请输入反向波的振幅:\n");
    scanf("%lf", &_bwd);
    printf("请输入反向波的频率:\n");
    scanf("%lf", &freq_bwd);
    printf("请输入反向波的波长:\n");
    scanf("%lf", &wavelen_bwd);
    
    // 循环每个时间点,计算波形并绘图
    for (n = 0; n < 1001; n++)
    {
        y_fwd = mxCreateDoubleMatrix(1, 101, mxREAL);
        y_bwd = mxCreateDoubleMatrix(1, 101, mxREAL);
        y_res = mxCreateDoubleMatrix(1, 101, mxREAL);
        for (j = 0; j < 101; j++)
        {
            *(mxGetPr(y_fwd) + j) = amp_fwd * sin(2 * 3.1416 * (t_data[n] * freq_fwd - x_data[j] / wavelen_fwd));
            *(mxGetPr(y_bwd) + j) = amp_bwd * sin(2 * 3.1416 * (t_data[n] * freq_bwd + x_data[j] / wavelen_bwd));
            *(mxGetPr(y_res) + j) = *(mxGetPr(y_fwd) + j) + *(mxGetPr(y_bwd) + j);
        }
        engEvalString(ep, "clf");
        engEvalString(ep, "plot(x , y_fwd , 'r', x , y_bwd , 'b', x , y_res , 'g')");
       
        engEvalString(ep, "title('波形合成')");
        engEvalString(ep, "xlabel('位置')");
        engEvalString(ep, "ylabel('振幅')");
        engEvalString(ep, "legend('正向波', '反向波', '驻波')");
        engEvalString(ep, "axis([0 10 -5 5])");
        engEvalString(ep, "M(n) = getframe()");
        mxGetPr(y_fwd); 
        mxGetPr(y_bwd);
        mxGetPr(y_res);
        mxDestroyArray(y_fwd);
        mxDestroyArray(y_bwd);
        mxDestroyArray(y_res);
    }
    // 关闭 MATLAB 引擎
    mxDestroyArray(t);
    mxDestroyArray(l);
    mxDestroyArray(x);
    engClose(ep);

    return 0;
}

然后出来的是只有坐标轴,而且在不停闪,右上角有个矩形也在闪

img

img

可以在 Visual Studio 中通过使用 MATLAB 的 COM 功能来调用 MATLAB 引擎,从而实现在 VS 中绘制动态驻波图。以下是一些参考步骤:

  1. 在 Visual Studio 中创建新的 C++ 控制台应用程序项目。
  2. 在项目中添加相应的头文件和链接库,以便能够使用 MATLAB 引擎 COM 接口连接 MATLAB 引擎。例如:
#include <mex.h>
#include <engine.h>

#pragma comment(lib, "libmx.lib")
#pragma comment(lib, "libeng.lib")
  1. 在代码中连接 MATLAB 引擎 COM 接口。
Engine *ep; // 声明 MATLAB 引擎指针变量
if (!(ep = engOpen(NULL))) {
    // 如果连接失败,则输出错误信息并退出程序
    fprintf(stderr, "\nUnable to connect to MATLAB Engine\n");
    return EXIT_FAILURE;
}
  1. 在 MATLAB 引擎中编写绘制动态驻波图的代码,并将其打包在一个函数中。

例如,以下示例代码使用 surf 函数绘制动态驻波图:

function [] = drawStandingWave()
    x = linspace(-2*pi,2*pi,100);
    t = 0:0.05:10*pi;
    [X,T] = meshgrid(x,t);
    Y = sin(X).*cos(T-X);
    surf(X,Y,T);
end
  1. 在 VS 中调用该 MATLAB 函数并获取返回结果。
// 调用 MATLAB 绘图函数
engEvalString(ep, "drawStandingWave();");

// 获取绘图窗口句柄
mxArray *hfigure = engGetVariable(ep, "gcf");
int figureHWnd = (int)mxGetScalar(mxGetProperty(hfigure, 0, "Number"));

// 设置绘图窗口为前台窗口
SetForegroundWindow((HWND)figureHWnd);
  1. 最后,通过在 VS 中使用 Windows API 函数 SetForegroundWindow 将 MATLAB 绘图窗口设置为前台窗口,即可在 VS 中显示动态驻波图。

希望这些步骤能够帮到您!

该回答引用ChatGPT:根据您提供的代码,我看到一个问题是您没有给正向波和反向波的振幅赋值,而是给了一个未定义的变量 _fwd 和 _bwd。您需要将这两个变量改为 amp_fwd 和 amp_bwd,并且在用户输入时也需要修改相应的变量名。

另外,您需要在循环开始前初始化变量 amp_fwd 和 amp_bwd,否则它们的值将是未定义的,导致计算的结果不正确。

还有一个问题是您在循环中每次都创建了新的 mxArray,但没有及时释放,会导致内存泄漏。您需要在循环结束后释放它们,可以使用 mxDestroyArray 函数。

最后,您需要在每次循环结束后使用 drawnow 函数来更新 MATLAB 图形窗口,否则图形将不会实时显示。

以下是修改后的代码:

#include "engine.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

int main()
{
    Engine* ep;
    mxArray* t = NULL, * l = NULL, * x = NULL, * y_fwd = NULL, * y_bwd = NULL, * y_res = NULL;
    double* t_data, * l_data, * x_data;
    double amp_fwd, freq_fwd, wavelen_fwd, amp_bwd, freq_bwd, wavelen_bwd;
    int i, j, n;

    // 连接到 MATLAB 引擎
    if (!(ep = engOpen(NULL)))
    {
        fprintf(stderr, "无法连接到 MATLAB 引擎\n");
        return EXIT_FAILURE;
    }

    // 创建 t 向量
    t = mxCreateDoubleMatrix(1, 1001, mxREAL);
    t_data = mxGetPr(t);
    for (i = 0; i < 1001; i++)
    {
        t_data[i] = i * 0.1;
    }

    // 创建 l 向量
    l = mxCreateDoubleScalar(10);
    l_data = mxGetPr(l);

    // 创建 x 向量
    x = mxCreateDoubleMatrix(1, 101, mxREAL);
    x_data = mxGetPr(x);
    for (i = 0; i < 101; i++)
    {
        x_data[i] = i * (*l_data) / 200;
    }

    // 获取用户输入参数
    printf("请输入正向波的振幅:\n");
    scanf("%lf", &amp_fwd);
    printf("请输入正向波的频率:\n");
    scanf("%lf", &freq_fwd);
    printf("请输入正向波的波长:\n");
    scanf("%lf", &wavelen_fwd);
    printf("请输入反向波的振幅:\n");
    scanf("%lf", &amp_bwd);
    printf("请输入反向波的频率:\n");
    scanf("%lf", &freq_bwd);
    printf("请输入反向波的波长:\n");
    scanf("%lf", &wavelen_bwd);

    // 循环每个时间点,计算波形并绘图
    for (n = 0; n < 1001; n++)
    {
        y_fwd = mxCreateDoubleMatrix(1, 101, mxREAL);
        y_bwd = mxCreateDoubleMatrix(1, 101, mxREAL);
        y_res = mxCreateDoubleMatrix(1, 101, mxREAL);
        for (j = 0; j < 101; j++)
        {
            *(mxGetPr(y_fwd) + j) = amp_fwd * sin(2 * 3.1416 * (t_data[n] * freq_fwd - x_data[j] / wavelen_fwd));
            *(mxGetPr(y_bwd) + j) = amp_bwd * sin(2 * 3.1416 * (t_data[n] * freq_bwd + x_data[j] / wavelen_bwd));
            *(mxGetPr(y_res) + j) = *(mxGetPr(y_fwd) + j) + *(mxGetPr(y_bwd) + j);
        }
        engEvalString(ep, "clf");
        engEvalString(ep, "subplot(3,1,1);plot(x,y_fwd,'r');title('正向波');axis([0 10 -2 2]);");
engEvalString(ep, "subplot(3,1,2);plot(x,y_bwd,'b');title('反向波');axis([0 10 -2 2]);");
engEvalString(ep, "subplot(3,1,3);plot(x,y_res,'g');title('合成波形');axis([0 10 -4 4]);");
engEvalString(ep, "drawnow;");
mxDestroyArray(y_fwd);
mxDestroyArray(y_bwd);
mxDestroyArray(y_res);
}
// 释放内存并关闭 MATLAB 引擎
mxDestroyArray(t);
mxDestroyArray(l);
mxDestroyArray(x);
engClose(ep);

return EXIT_SUCCESS;
}

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
根据您提供的信息,我大致看出两个问题:

  1. 坐标轴闪烁不停
  2. MATLAB图像不出来

首先,关于坐标轴闪烁不停的问题,可能是由于代码中的图形更新频率太快导致的。您可以尝试在每次循环中加入一个延时,比如使用Sleep函数,给MATLAB足够的时间来更新图形。例如在每次循环中加入 Sleep(100)。同时,您也可以尝试在执行完打开引擎的操作后,添加 engEvalString(ep, "uiwait(gcf)"); 代码,让程序暂停等待用户界面(MATLAB图形界面)加载完成。

接下来,关于MATLAB图像不出来的问题,根据您提供的代码,我发现在循环每个时间点,计算波形并绘图的部分,代码中只对y_fwd、y_bwd、y_res数组赋值,而没有将这些向量传给MATLAB进行绘图。您可以在每次循环结束后,添加以下代码将向量 y_fwd、y_bwd、y_res 传送到 MATLAB 绘图:

mxArray* pArray[3] = { y_fwd, y_bwd, y_res };
for (int k = 0; k < 3; k++)
{
    if (pArray[k] != NULL)
    {
        char command[256];
        sprintf(command, "x%d=x',y%d=y(:,%d)',", k, k, k+1);
        engEvalString(ep, command);
        engPutVariable(ep, command+1, pArray[k]);
    }
}
engEvalString(ep, "clf");
engEvalString(ep, "plot(x0 , y0 , 'r', x1 , y1 , 'b', x2 , y2 , 'g')");
engEvalString(ep, "title('波形合成')");
engEvalString(ep, "xlabel('位置')");
engEvalString(ep, "ylabel('振幅')");
engEvalString(ep, "legend('正向波', '反向波', '驻波')");
engEvalString(ep, "axis([0 10 -5 5])");

其中mxArray* pArray[3] = { y_fwd, y_bwd, y_res }定义了三个向量的数组,通过循环将每个向量传送到MATLAB中,再调用MATLAB的plot函数绘制图像。

同时,如果您使用的是最新版的MATLAB(R2019a及以后版本),可以试试在代码执行前添加以下两行代码,用以禁用MATLAB的硬件加速。这个问题的原因可能是由于硬件加速与VS不兼容所导致的。

engEvalString(ep, "matlab.graphics.Renderer.use('software')");
engEvalString(ep, "set(groot,'DefaultFigureRenderer','painters')");

最终完整代码如下:

#include "engine.h"已黑化的小白 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

int main()
{
    Engine* ep;
    mxArray* t = NULL, * l = NULL, * x = NULL, * y_fwd = NULL, * y_bwd = NULL, * y_res = NULL;
    double* t_data, * l_data, * x_data;
    double amp_fwd, freq_fwd, wavelen_fwd, amp_bwd, freq_bwd, wavelen_bwd;
    int i, j, n;

    // 连接到 MATLAB 引擎
    if (!(ep = engOpen(NULL)))
    {
        fprintf(stderr, "无法连接到 MATLAB 引擎\n");
        return EXIT_FAILURE;
    }

    // 添加禁用硬件加速代码
    engEvalString(ep, "matlab.graphics.Renderer.use('software')");
    engEvalString(ep, "set(groot,'DefaultFigureRenderer','painters')");

    // 创建 t 向量
    t = mxCreateDoubleMatrix(1, 1001, mxREAL);
    t_data = mxGetPr(t);
    for (i = 0; i < 1001; i++)
    {
        t_data[i] = i * 0.1;
    }

    // 创建 l 向量
    l = mxCreateDoubleScalar(10);
    l_data = mxGetPr(l);

    // 创建 x 向量
    x = mxCreateDoubleMatrix(1, 101, mxREAL);
    x_data = mxGetPr(x);
    for (i = 0; i < 101; i++)
    {
        x_data[i] = i * (*l_data) / 200;
    }

    // 获取用户输入参数
    printf("请输入正向波的振幅:\n");
    scanf("%lf", &amp_fwd);
    printf("请输入正向波的频率:\n");
    scanf("%lf", &freq_fwd);
    printf("请输入正向波的波长:\n");
    scanf("%lf", &wavelen_fwd);
    printf("请输入反向波的振幅:\n");
    scanf("%lf", &amp_bwd);
    printf("请输入反向波的频率:\n");
    scanf("%lf", &freq_bwd);
    printf("请输入反向波的波长:\n");
    scanf("%lf", &wavelen_bwd);

    // 循环每个时间点,计算波形并绘图
    for (n = 0; n < 1001; n++)
    {
        y_fwd = mxCreateDoubleMatrix(1, 101, mxREAL);
        y_bwd = mxCreateDoubleMatrix(1, 101, mxREAL);
        y_res = mxCreateDoubleMatrix(1, 101, mxREAL);
        for (j = 0; j < 101; j++)
        {
            *(mxGetPr(y_fwd) + j) = amp_fwd * sin(2 * 3.1416 * (t_data[n] * freq_fwd - x_data[j] / wavelen_fwd));
            *(mxGetPr(y_bwd) + j) = amp_bwd * sin(2 * 3.1416 * (t_data[n] * freq_bwd + x_data[j] / wavelen_bwd));
            *(mxGetPr(y_res) + j) = *(mxGetPr(y_fwd) + j) + *(mxGetPr(y_bwd) + j);
        }

        // 将向量传送给 MATLAB 绘制图像
        mxArray* pArray[3] = { y_fwd, y_bwd, y_res };
        for (int k = 0; k < 3; k++)
        {
            if (pArray[k] != NULL)
            {
                char command[256];
                sprintf(command, "x%d=x',y%d=y(:,%d)',", k, k, k+1);
                engEvalString(ep, command);
                engPutVariable(ep, command+1, pArray[k]);
            }
        }
        engEvalString(ep, "clf");
        engEvalString(ep, "plot(x0 , y0 , 'r', x1 , y1 , 'b', x2 , y2 , 'g')");
        engEvalString(ep, "title('波形合成')");
        engEvalString(ep, "xlabel('位置')");
        engEvalString(ep, "ylabel('振幅')");
        engEvalString(ep, "legend('正向波', '反向波', '驻波')");
        engEvalString(ep, "axis([0 10 -5 5])");

        // 暂停等待界面加载完成
        engEvalString(ep, "uiwait(gcf)");

        mxGetPr(y_fwd);
        mxGetPr(y_bwd);
        mxGetPr(y_res);
        mxDestroyArray(y_fwd);
        mxDestroyArray(y_bwd);
        mxDestroyArray(y_res);

        // 添加延时防止刷新过快
        Sleep(100);
    }

    // 关闭 MATLAB 引擎
    mxDestroyArray(t);
    mxDestroyArray(l);
    mxDestroyArray(x);
    engClose(ep);

    return 0;
}

希望以上解答能够帮到您,如果还有问题欢迎继续提问!
如果我的回答解决了您的问题,请采纳!

该回答引用ChatGPT
根据你提供的信息,可能是以下几个问题导致MATLAB图像不出来:
1. MATLAB引擎没有正确连接:在代码中,可以看到使用`engOpen`函数连接MATLAB引擎,如果连接失败,就无法正确调用MATLAB绘图函数。可以尝试检查一下MATLAB引擎是否正确安装,并且确认路径是否正确。
2. 绘图函数参数不正确:在代码中,可以看到使用`plot`函数绘制图像,如果参数不正确,就无法正确绘制图像。可以尝试检查一下`plot`函数的参数是否正确,特别是数据类型和维度是否匹配。
3. 绘图函数没有被正确调用:在代码中,可以看到使用`EvalString`函数调用MATLAB绘图函数,如果调用失败,就无法正确绘制图像。可以尝试检查一下`EvalString`函数调用的语句是否正确,特别是语法和拼写是否正确。
下面是一些可能有用的建议:
1. 确认MATLAB引擎是否正确安装,并且确认路径是否正确。
2. 尝试使用MATLAB命令行手动绘制动态驻波图像,以确认MATLAB是否可以正确绘制图像。
3. 尝试使用其他绘图函数,例如`scatter`或`line`,以确认绘图函数是否正确调用。
4. 尝试使用`pause`函数在每个时间点暂停一段时间,以便观察图像。
5. 尝试使用`drawnow`函数在每个时间点强制刷新图像,以便观察图像。
6. 尝试使用`M(n) = getframe(gcf)`函数将图像保存为视频,以便观察图像。
下面是修改后的代码,可以尝试运行一下看看是否能够正确绘制图像:

#include "engine.h"
#include
#include
#include
#include
int main()
{
Engine* ep;
mxArray* t = NULL, *l = NULL, *x = NULL, *y_fwd = NULL, *y_bwd = NULL, *y_res = NULL;
double* t_data, *l_data, *x_data;
double amp_fwd, freq_fwd, wavelen_fwd, amp_bwd, freq_bwd, wavelen_bwd;
int i, j, n;
// 连接到 MATLAB 引擎
if (!(ep = engOpen(NULL)))
{
fprintf(stderr, "无法连接到 MATLAB 引擎\
");
return EXIT_FAILURE;
}
// 创建 t 向量
t = mxCreateDoubleMatrix(1, 1001, mxREAL);
t_data = mxGetPr(t);
for (i = 0; i < 1001; i++)
{
t_data[i] = i * 0.1;
}
// 创建 l 向量
l = mxCreateDoubleScalar(10);
l_data = mxGetPr(l);
// 创建 x 向量
x = mxCreateDoubleMatrix(1, 101, mxREAL);
x_data = mxGetPr(x);
for (i = 0; i < 101; i++)
{
x_data[i] = i * (*l_data) / 200;
}
// 获取用户输入参数
printf("请输入正向波的振幅:\
");
scanf("%lf", &_fwd);
printf("请输入正向波的频率:\
");
scanf("%lf", &freq_fwd);
printf("请输入正向波的波长:\
");
scanf("%lf", &wavelen_fwd);
printf("请输入反向波的振幅:\
");
scanf("%lf", &_bwd);
printf("请输入反向波的频率:\
");
scanf("%lf", &freq_bwd);
printf("请输入反向波的波长:\
");
scanf("%lf", &wavelen_bwd);
// 循环每个时间点,计算波形并绘图
for (n = 0; n < 1001; n++)
{
y_fwd = mxCreateDoubleMatrix(1, 101, mxREAL);
y_bwd = mxCreateDoubleMatrix(1, 101, mxREAL);
y_res = mxCreateDoubleMatrix(1, 101, mxREAL);
for (j = 0; j < 101; j++)
{
*(mxGetPr(y_fwd) + j) = amp_fwd * sin(2 * 3.1416 * (t_data[n] * freq_fwd - x_data[j] / wavelen_fwd));
*(mxGetPr(y_bwd) + j) = amp_bwd * sin(2 * 3.1416 * (t_data[n] * freq_bwd + x_data[j] / wavelen_bwd));
*(mxGetPr(y_res) + j) = *(mxGetPr(y_fwd) + j) + *(mxGetPr(y_bwd) + j);
}
engEvalString(ep, "clf");
engEvalString(ep, "plot(x , y_fwd , 'r', x , y_bwd , 'b', x , y_res , 'g')");
engEvalString(ep, "title('波形合成')");
engEvalString(ep, "xlabel('位置')");
engEvalString(ep, "ylabel('振幅')");
engEvalString(ep, "legend('正向波', '反向波', '驻波')");
engEvalString(ep, "axis([0 10 -5 5])");
engEvalString(ep, "drawnow");
mxGetPr(y_fwd);
mxGetPr(y_bwd);
mxGetPr(y_res);
mxDestroyArray(y_fwd);
mxDestroyArray(y_bwd);
mxDestroyArray(y_res);
}
// 关闭 MATLAB 引擎
mxDestroyArray(t);
mxDestroyArray(l);
mxDestroyArray(x);
engClose(ep);
return 0;
}