C程序调用matlab (Win8 64 bit + VS 2013 + Matlab R2014a)

2024-06-15 08:58

本文主要是介绍C程序调用matlab (Win8 64 bit + VS 2013 + Matlab R2014a),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Visual Studio和MATLAB混合编程,有两种方法: 

MATLAB调用C程序

     用MATLAB的mex命令调用VS或其他编译器,将以一定方式编写出的C文件编译成.mexw32(针对win32)或者.mexw64(针对win64),然后MATLAB就可以用调用动态链接库的方式,调用C程序。这一过程中,只需要在安装好编译器的前提下,执行:

mex -setup

mbuild -setup

并按照提示按部就班地帮助MATLAB找到C编译器就可以了。遇到MATLAB找不到Visual Stdio的情况时,可按照官方网站提供的方法,例如如果MATLAB找不到已安装的Visual Studio 2013,则在

http://www.mathworks.com/matlabcentral/fileexchange/44408-matlab-mex-support-for-visual-studio-2013--and-mbuild-

下载官方提供的文件,按照README的要求将文件复制到指定目录下即可。

README:

复制代码
The files * msvc120engmatopts.bat* msvc120opts.bat* msvc120opts.stp
should be copied to C:\Program Files\MATLAB\R2013a\bin\win64\mexopts .The files * msvc120compp.bat* msvc120compp.stp
should be copied to C:\Program Files\MATLAB\R2013a\bin\win64\mbuildopts .
复制代码

 



VS调用MATLAB---Engine

  (目前见到的都是VS,其他编译器如codeblocks,或不提供这项功能)


     由VS去调用MATLAB,因为归根结底,许多底层的代码都依赖于C/C++语言,如果要使用MATLAB进行实时的数据处理,那么必然是使用C/C++(从操作系统内核、套接字,或者设备)获取数据,再调用MATLAB进行处理。切入正题:

     1   首先正确地安装好环境,如下是我使用的环境:

    x64

    Windows 8 

    VS2013

    MATLAB R2014a(安装目录为D:\R2014a)。

     2    下面是VS路径的包含

     右键项目—属性—VC++目录

               —包含目录,添加D:\R2014a\extern\include;(注意分号)

               —库目录,添加D:\R2014a\extern\lib\win64\microsoft;

            —C/C++(—常规),添加附加包含目录D:\R2014a\extern\include\;

          —链接器

               —常规,添加附加库目录D:\R2014a\extern\lib\win64\microsoft;

               —输入,添加附加依赖项:libeng.lib;libmat.lib;libmex.lib;libmx.lib;mclmcrrt.lib;mclmcr.lib;

     3   系统环境变量:PATH里添加D:\R2014a\bin\win64; 帮助VS找到MATLAB的提供的动态链接库。

   *4   注册MATLAB服务器:cmd,在D:\R2014a\bin目录下运行

matlab \regserver

    大概是开启MATLAB Server模式,接收VS的调用请求吧。 但是我并没有执行这一句。

    5  下面写C/C++程序:

    添加头文件以及动态链接库

#include "engine.h"#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "libeng.lib")
#pragma comment(lib, "libmx.lib")
#pragma comment(lib, "libmat.lib")

    打开引擎(引擎用来调用MATLAB):

复制代码
Engine* pEng = NULL;if (!(pEng = engOpen(NULL))){printf("Open matlab enging fail!");getchar();return -1;}
复制代码

    引擎打开函数openEng调用完毕后一定要检查是否打开成功(类似malloc函数,申请完内存一定要检查是否申请成功),因为就算pEng==NULL,在函数engEvalString执行中也不会抛出异常的,只会导致engGetVariable执行失败,当然咯,因为根本没执行嘛,哪来的variable?

    然后可以调用啦,一切的matlab命令都可以通过下面这个函数传入MATLAB执行,类似于Linux的系统调用exec("...")和windows的system("..."):

engEvalString(pEng, "x=0:0.01:pi); y=sin(x); plot(x, y)");

    如果要得到MATLAB的返回结果:

engEvalString(pEng, "x=0:0.02:3.14; y=sin(x); plot(x, y)");
mxArray *x= engGetVariable(pEng, "x");
mxArray *y= engGetVariable(pEng, "y");
double * _x = mxGetPr(x);
double * _x = mxGetPr(y);
//此时_x为x数组,_y为y数组

    由于MATLAB里面,数据都将看成矩阵来处理,因此返回结果也是以Array的方式返回,如果是单个值,就是array[0],否则为array[0..n-1],如何得到n呢?还是用函数engGetVariable咯,可以先执行n=length(x),再将n传回

    执行结束后,记得关闭引擎

 

if(pEng)engClose(pEng);

 

    注意一旦关闭,就不能再使用pEng了,否则会抛出异常。并且,在关闭引擎后,原本在执行过程中得到的figures也会关闭。在我的课题里面,引擎是在程序开始时打开,程序最终退出时才关闭。

 

ERRORS:

6   如果在编译期间出现“找不到XXX.lib”的情况,检查路径是否正确添加,环境变量设置是否成功,环境变量重启之后才生效。

参考: http://blog.csdn.net/u010275404/article/details/46645465

7   如果编译链接通过,运行起来还是有异常,检查matlab server是否有注册成功:运行matlab /regserver,再试一试。

8   因为调用MATLAB执行的命令是以字符串形式传入的,千万注意字符串里面的特殊符号、空格。特殊符号前面需要加上反斜杆,若有空格,依据MATLAB的语法,应使用单引号。例如:

engEvalString(pEng,"cd \'E:\\Desktop\\Alilce and Bob\' ");

 

9  如果遇到ERROR LNK2019,如:

复制代码
错误    1    error LNK2019: 无法解析的外部符号 _mxGetPr,该符号在函数 "void __cdecl dataProcessing(struct engine *)" (?dataProcessing@@YAXPAUengine@@@Z) 中被引用    C:\Users\OurEDA\Desktop\Ahotspot\Models\RSS CSI Models\matlab\main.obj    matlab
错误    2    error LNK2019: 无法解析的外部符号 _mxDestroyArray,该符号在函数 "void __cdecl dataProcessing(struct engine *)" (?dataProcessing@@YAXPAUengine@@@Z) 中被引用    C:\Users\OurEDA\Desktop\Ahotspot\Models\RSS CSI Models\matlab\main.obj    matlab
错误    3    error LNK2019: 无法解析的外部符号 _engEvalString,该符号在函数 "void __cdecl dataProcessing(struct engine *)" (?dataProcessing@@YAXPAUengine@@@Z) 中被引用    C:\Users\OurEDA\Desktop\Ahotspot\Models\RSS CSI Models\matlab\main.obj    matlab
错误    4    error LNK2019: 无法解析的外部符号 _engOpen,该符号在函数 _main 中被引用    C:\Users\OurEDA\Desktop\Ahotspot\Models\RSS CSI Models\matlab\main.obj    matlab
错误    5    error LNK2019: 无法解析的外部符号 _engClose,该符号在函数 _main 中被引用    C:\Users\OurEDA\Desktop\Ahotspot\Models\RSS CSI Models\matlab\main.obj    matlab
错误    6    error LNK2019: 无法解析的外部符号 _engGetVariable,该符号在函数 "void __cdecl dataProcessing(struct engine *)" (?dataProcessing@@YAXPAUengine@@@Z) 中被引用    C:\Users\OurEDA\Desktop\Ahotspot\Models\RSS CSI Models\matlab\main.obj    matlab
错误    7    error LNK1120: 6 个无法解析的外部命令    C:\Users\OurEDA\Desktop\Ahotspot\Models\RSS CSI Models\Debug\matlab.exe    1    1    matlab
复制代码

  检查MATLAB和VS是否运行在同一平台上,如果MATLAB是x64,那么配置管理器中一定要选中x64,否则选Win32:

  右键项目——在配置管理器的下拉菜单里选中正确的平台,然后按照上面所述的过程重新配置路径

 


下面是一个例子,绘制y = sin(t) 的图像:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "engine.h"#pragma comment( lib, "libeng.lib" )
#pragma comment( lib, "libmx.lib" )
#pragma comment( lib, "libmat.lib" )int main()
{Engine *ep;if (!(ep = engOpen("\0"))){fprintf(stderr, "\nCan't start MATLAB engine\n");return EXIT_FAILURE;}int Nsample = 50;const double PI = 3.1415926;double *t = new double[Nsample];for (int i = 0; i < Nsample; i++){t[i] = i * 2 * PI / Nsample;}mxArray *T = NULL, *result = NULL;T = mxCreateDoubleMatrix(1, Nsample, mxREAL);memcpy((void *)mxGetPr(T), (void *)t, Nsample*sizeof(t[0]));engPutVariable(ep, "T", T);engEvalString(ep, "Y=sin(T);");engEvalString(ep, "plot(T,Y);");engEvalString(ep, "title('y=sin(t)');");engEvalString(ep, "xlabel('t');");engEvalString(ep, "ylabel('y');");printf("Hit return to continue\n\n");fgetc(stdin);mxDestroyArray(T);engEvalString(ep, "close;");engClose(ep);return EXIT_SUCCESS;
}

C程序调用matlab生成的dll

       如果需要matlab完成的功能比较通用,如果用上述方法,则会产生大量的重复代码。这里要讲的方法将对matlab 的调用做成一个模块,这样每次使用时只需调用这个模块就可以了。        首先将需要matlab完成的功能做成一个matlab函数,然后利用mcc命令编译,得到h、dll、lib等文件,在C工程中只需加入上述文件即可。

生成dll文件
一句命令mcc -W cpplib:add -T link:lib add.m
前面的add表示生成的dll文件名,后面的add.m顾名思义是.m文件名。生成后会多出8个文件,有用的是add.ctfadd.dll add.lib add.h4个文件,据说新版的Matlab不会生成.ctf文件。

二、VC6.0中调用生成的dll文件
上面生成的dll文件,我们可以借助VC6.0的Depends工具查看导出函数名,但是我们要调用导出函数必须要知道函数的形参返回类型等,这里要借助.h文件,它包含了导出函数的声明,下面以实例来讲解使用方法:
1、add.m文件

function [a,b]=add(x,y) 
a=2*x+y; 
b=3*y;
end

注意了add函数有两个返回值,可以猜测一下在C++中是如何处理的;

2、add.h文件
截取其中一段关键代码如下:

extern void add(int nargout, mwArray& a, mwArray& b, const mwArray& x, const mwArray& y);

实际上函数的返回是变相的放到形参中的,依次是输出参数个数,输出参数,输入参数。PS 现在做的这个项目中用户自定义算法dll使用的规则和这里类似!

3、C++中调用dll文件
(1)新建空工程,将上面提及的4个文件放到工程目录下;
(2)VC++目录中包含目录:matlab 内的include目录
比如我的是 E:\MATLAB7\extern\include
(3)VC++目录中库目录:matlab 内的lib目录
E:\MATLAB7\extern\lib\win32\microsoft\msvc60,要根据VC++版本修改!
(4)工程属性-》连接-》输入-》附加依赖项
输入:add.lib mclmcrrt.lib mclmcr.lib,第一个是生成的。或者在预处理中加入下面代码

#pragma comment(lib, "mclmcrrt.lib")
#pragma comment(lib, "mclmcr.lib")
#pragma comment(lib, "add.lib")

4、C++代码

#include <iostream>
#include "add.h"
using namespace std;
int main()
{if(!addInitialize()){cout<<"initilize failed!!!"<<endl;return -1;}mwArray a(1,1,mxDOUBLE_CLASS);mwArray b(1,1,mxDOUBLE_CLASS);a(1,1)=20;b(1,1)=30;mwArray x(1,1,mxDOUBLE_CLASS);mwArray y(1,1,mxDOUBLE_CLASS);//输出参数个数,输出参数,输入参数。add(2,x,y,a,b);double *i=new double;double *j=new double ;x.GetData(i,1);y.GetData(j,1);    cout<<"x="<<*i<<"  y="<<*j<<endl; getchar();return 0;
}

注意:addInitialize()一定要!




下面是另一个例子:

       在做通信仿真时通常是给地一组信噪比,然后通过仿真得到在每个信噪比下的误码率,最后绘制出误码率对信噪比的曲线。

       以前的做法是用C仿真,并将结果存在txt文件中,最后让matlab从txt文件中读取数据并绘图。

       利用这里的方法,可以写一个matlab绘图的模块,并在C程序的最后调用,这样就能自动完成绘图了。

Matlab代码:

function showBER(SNR_indB,BER)
semilogy(SNR_indB,BER,'-o','linewidth',2);
grid on
xlabel('E_b/N_0(dB)');
ylabel('BER');
在matlab命令行中输入:mcc -B csharedlib:showBER showBER.m  得到一组文件

将其中的.dll .h .lib文件拷贝到C工程中。

在需要调用绘图模块的cpp文件中加入如下代码

#include "showBER.h"
#pragma comment( lib, "libeng.lib" )
#pragma comment( lib, "libmx.lib" )
#pragma comment( lib, "libmat.lib" )
#pragma comment( lib, "mclmcrrt.lib" )
#pragma comment( lib, "showBER.lib" )
下面的一段代码显示了调用绘图模块的方法:

double SNR[] = { 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5 };
double BER[] = { 9.728816e-002, 8.099609e-002, 5.633803e-002, 3.733608e-002, 1.253970e-002, 3.936489e-003, 1.206820e-003, 2.104052e-004, 3.109879e-005, 3.365857e-006, 2.565067e-007 };
int len = sizeof(SNR) / sizeof(SNR[0]);showBERInitialize();mxArray* xSNR = mxCreateDoubleMatrix(1, len, mxREAL);
memcpy(mxGetPr(xSNR), (void*)SNR, sizeof(SNR));
mxArray* xBER = mxCreateDoubleMatrix(1, len, mxREAL);
memcpy(mxGetPr(xBER), (void*)BER, sizeof(BER));mlfShowBER(xSNR, xBER);
system("PAUSE");showBERTerminate();
1在调用绘图模块之前需要调用showBERInitialize

2在调用绘图模块之后需要调用showBERTerminate

3使用mxCreateDoubleMatrix 和 memcpy 函数将C程序中的变量送入matlab中

4通过mlfShowBER调用matlab模块。而mlf***函数的调用格式需要参考***.h(此例为showBER.h)文件中的声明。



ERROR:

我没法在matlab中执行上述命令的原因。我没有LICENSE!!!

在matlab命令行中输入: !mcc

得到license信息。

>> !mcc
Error: Could not check out a Compiler license: 
SIGN= keyword required but missing from the license certificate. 
 This is probably because the license is older than the application 
 You need to obtain a SIGN= version of this license from your vendor. 


破解参考:

http://www.ilovematlab.cn/thread-263651-2-1.html


调用指南百度参考:

http://wenku.baidu.com/view/2aa0632a0066f5335a812178.html

这篇关于C程序调用matlab (Win8 64 bit + VS 2013 + Matlab R2014a)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1063003

相关文章

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

EMLOG程序单页友链和标签增加美化

单页友联效果图: 标签页面效果图: 源码介绍 EMLOG单页友情链接和TAG标签,友链单页文件代码main{width: 58%;是设置宽度 自己把设置成与您的网站宽度一样,如果自适应就填写100%,TAG文件不用修改 安装方法:把Links.php和tag.php上传到网站根目录即可,访问 域名/Links.php、域名/tag.php 所有模板适用,代码就不粘贴出来,已经打

跨系统环境下LabVIEW程序稳定运行

在LabVIEW开发中,不同电脑的配置和操作系统(如Win11与Win7)可能对程序的稳定运行产生影响。为了确保程序在不同平台上都能正常且稳定运行,需要从兼容性、驱动、以及性能优化等多个方面入手。本文将详细介绍如何在不同系统环境下,使LabVIEW开发的程序保持稳定运行的有效策略。 LabVIEW版本兼容性 LabVIEW各版本对不同操作系统的支持存在差异。因此,在开发程序时,尽量使用

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

这些心智程序你安装了吗?

原文题目:《为什么聪明人也会做蠢事(四)》 心智程序 大脑有两个特征导致人类不够理性,一个是处理信息方面的缺陷,一个是心智程序出了问题。前者可以称为“认知吝啬鬼”,前几篇文章已经讨论了。本期主要讲心智程序这个方面。 心智程序这一概念由哈佛大学认知科学家大卫•帕金斯提出,指个体可以从记忆中提取出的规则、知识、程序和策略,以辅助我们决策判断和解决问题。如果把人脑比喻成计算机,那心智程序就是人脑的

matlab读取NC文件(含group)

matlab读取NC文件(含group): NC文件数据结构: 代码: % 打开 NetCDF 文件filename = 'your_file.nc'; % 替换为你的文件名% 使用 netcdf.open 函数打开文件ncid = netcdf.open(filename, 'NC_NOWRITE');% 查看文件中的组% 假设我们想读取名为 "group1" 的组groupName

【LabVIEW学习篇 - 21】:DLL与API的调用

文章目录 DLL与API调用DLLAPIDLL的调用 DLL与API调用 LabVIEW虽然已经足够强大,但不同的语言在不同领域都有着自己的优势,为了强强联合,LabVIEW提供了强大的外部程序接口能力,包括DLL、CIN(C语言接口)、ActiveX、.NET、MATLAB等等。通过DLL可以使用户很方便地调用C、C++、C#、VB等编程语言写的程序以及windows自带的大

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87