[Matlab] matlab与C/C++混合编程汇总

原创 2016年06月01日 15:37:30


matlab 与外部程序的编程接口两大类:

               一是 如何在matlab里调用其他语言写的代码。 (见例子:使用C-MEX技术,ActiveX技术)

               二是 如何在其他语言里调用matlab。 (见 使用matlab引擎, MAT数据交换, matlab发布com组件, DeployTool)


matlab接口技术包含以下几个方面:

1. 数据导入导出,主要是MAT文件数据的导入导出。

2.普通的动态链接库dll文件的交互,Matlab6.5起,直接matlab环境中调用dll文件导出的函数。

3.matlab环境中调用c/c++语言代码的接口,通过MEX(MATLAB EXecutable)技术实现。C/C++代码通过实现特殊的入口函数,编译成MEX文件(实际dll),可以像一般的m文件被调用,调用级别比M函数高。

4.matlab环境中调用java,6.0版本起,matlab增加java支持,其工作界面GUI也是java编写的,且包含了Java虚拟机。

5.对COM与DDE的支持,5.1后DDE没再增加新内容,6.5后推荐COM接口。matlab的com编译器能将matlab函数转换成COM对象供多种语言使用。

6.matlab使用网络服务或者和串口通讯。


使用matlab引擎

前段客户端使用 matlab引擎(matlab的一组接口函数engXXXX) 与后台启动的matlab进程 进行数据交换和命令的传送。

几乎可以利用matlab的全部功能,但需要计算机上安装matlab软件,执行效率低,不宜用于商业应用软件。

VC++ 开发环境,需要添加Include:  {matlab安装目录}\extern\include\         Library Files: {matlab安装目录}\extern\lib\win32\microsoft\


C and Fortran Engine Library Functions


engOpen (C and Fortran) Start MATLAB engine session
engOpenSingleUse (C) Start MATLAB engine session for single, nonshared use
engClose (C and Fortran) Quit MATLAB engine session
Engine (C) Type for MATLAB engine
engEvalString (C and Fortran) Evaluate expression in string
engGetVariable (C and Fortran) Copy variable from MATLAB engine workspace
engPutVariable (C and Fortran) Put variable into MATLAB engine workspace
engGetVisible (C) Determine visibility of MATLAB engine session
engSetVisible (C) Show or hide MATLAB engine session
engOutputBuffer (C and Fortran) Specify buffer for MATLAB output

engPutArray 和 engGetArray 已过时,被engPutVariable 和 engGetVariable取替,但仍可使用。


 
        mxArray * T = mxCreateDoubleMatrix(1, 10, mxREAL);
	memcpy((char *) mxGetPr(T), (char *) time, 10*sizeof(double));

	/*
	 * Place the variable T into the MATLAB workspace
	 */
	engPutVariable(ep, "T", T);

	/*
	 * Evaluate a function of time, distance = (1/2)g.*t.^2
	 * (g is the acceleration due to gravity)
	 */
	engEvalString(ep, "D = .5.*(-9.8).*T.^2;");

	 /*
	 * Use engOutputBuffer to capture MATLAB output. Ensure first that
	 * the buffer is always NULL terminated.
	 */
	 buffer[BUFSIZE] = '\0';
	 engOutputBuffer(ep, buffer, BUFSIZE);

	 /*
	 * the evaluate string returns the result into the
	 * output buffer.
	 */
	 engEvalString(ep, "whos");
	 MessageBox ((HWND)NULL, (LPSTR)buffer, (LPSTR) "MATLAB - whos", MB_OK);

完整项目:demo1


MAT数据交换

 MATLAB中操作MAT文件命令 load , save
 
 windows系统中可以使用type查看mat文件的版本等信息。
>> type mattest.mat
MATLAB 5.0 MAT-file, Platform: PCWIN, Created on: Mon May 30 13:55:35 2016       
C and Fortran MAT-File Library Functions
matOpen (C and Fortran) Open MAT-file
matClose (C and Fortran) Close MAT-file
MATFile (C and Fortran) Type for MAT-file
matGetVariable (C and Fortran) Array from MAT-file
matGetVariableInfo (C and Fortran) Array header information only
matGetNextVariable (C and Fortran) Next array in MAT-file
matGetNextVariableInfo (C and Fortran) Array header information only
matPutVariable (C and Fortran) Array to MAT-file
matPutVariableAsGlobal (C and Fortran) Array to MAT-file as originating from global workspace
matDeleteVariable (C and Fortran) Delete array from MAT-file
matGetDir (C and Fortran) List of variables in MAT-file
matGetFp (C) File pointer to MAT-file
mxIsFromGlobalWS (C and Fortran) Determine whether array was copied from MATLAB global workspace
	pmat = matOpen(file,"r");
	if (NULL == pmat){	
		sprintf(buf, "打开文件错误 %s",file);
		MessageBox(buf);
		return;	
	}

	m_list.AddString("打开文件");

	/** read in each array we just wrote **/
	pa1 = matGetVariable(pmat,"LocalDouble");
	if(NULL == pa1){
		MessageBox("读取 matrix LocalDouble failed");
		return;
	}
	m_list.AddString("读取matix LocalDouble");

	if(mxGetNumberOfDimensions(pa1) != 2){
		MessageBox("矩阵保存错误:结果不是两维!");
		return;
	}
	m_list.AddString("矩阵是两维的");

	pa2 = matGetVariable(pmat,"GlobalDouble");
	if(NULL == pa2){
		MessageBox("读取 matrix GlobalDouble failed");
		return;
	}
	m_list.AddString("读取GlobalDouble");

	if( !(mxIsFromGlobalWS(pa2)) ) {
		MessageBox("全局保存错误,GlobalDouble不是全局的");
	}
	m_list.AddString("GlobalDouble是全局的");

	pa3 = matGetVariable(pmat,"LocalString");
	if(NULL == pa3){
		MessageBox("读取LocalString错误");
		return;
	}
	m_list.AddString("读取LocalString");

	status = mxGetString(pa3, str, sizeof(str));
	if( 0 != status){
		MessageBox("空间不足");
			return;
	}
	if( strcmp(str,"MATLAB: the language of technical computing") ){
		MessageBox("字符串保存错误");
	}
        m_list.AddString("字符串保存完整");

	/** clean up before exit **/
	mxDestroyArray(pa1);
	mxDestroyArray(pa2);
	mxDestroyArray(pa3);

	if(matClose(pmat) != 0){
		sprintf(buf, "",file);
		MessageBox(buf);
		return;
	}
	m_list.AddString("关闭文件");
完整项目:demo2

使用C-MEX技术

对于影响matlab执行速度的for、while等循环,可以编写相应的C/Fortan子函数,编译成MEX文件,提高运行速度。
对于一些访问硬件的底层操作,A/D、D/A或者中断,可以通过MEX直接访问,克服matlab不足。
matlab编程效率高,尽量使用maltab编程,对于耗时或者功能受限的部分采用mex编程。

windows里需要对mex编译器进行配置编译
>> mex -setup
please choose your compiler for building external interface(MEX) files:
Would you like mex to locate installed compilers[y]/n?

按照提示选择对应的编译器,最终生成mexopts.bat

C MEX Library Functions
mexFunction Entry point to C/C++ or Fortran MEX file
mexFunctionName Name of current MEX function
mexAtExit Register function to call when MEX function clears or MATLAB terminates
mexCallMATLAB Call MATLAB function, user-defined function, or MEX file
mexCallMATLABWithTrap Call MATLAB function, user-defined function, or MEX-file and capture error information
mexEvalString Execute MATLAB command in caller workspace
mexEvalStringWithTrap Execute MATLAB command in caller workspace and capture error information
mexGet Value of specified graphics property
mexSet Set value of specified graphics property
mexGetVariable Copy of variable from specified workspace
mexGetVariablePtr Read-only pointer to variable from another workspace
mexPutVariable Array from MEX-function into specified workspace
mexPrintf ANSI C PRINTF-style output routine
mexSetTrapFlag Control response of MEXCALLMATLAB to errors
mexErrMsgIdAndTxt Display error message with identifier and return to MATLAB prompt
mexWarnMsgIdAndTxt Warning message with identifier
mexErrMsgTxt Display error message and return to MATLAB prompt
mexWarnMsgTxt Warning message
mexIsLocked Determine if MEX-file is locked
mexLock Prevent clearing MEX-file from memory
mexUnlock Allow clearing MEX-file from memory
mexMakeArrayPersistent Make array persist after MEX file completes
mexMakeMemoryPersistent Make memory allocated by MATLAB software persist after MEX-function completes

入口函数:

C Syntax

#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, 
  const mxArray *prhs[])

Fortran Syntax

#include "fintrf.h"
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
integer nlhs, nrhs
mwPointer plhs(*), prhs(*)

Arguments

nlhs

Number of expected output mxArrays

plhs

Array of pointers to the expected output mxArrays

nrhs

Number of input mxArrays

prhs

Array of pointers to the input mxArrays. Do not modify any prhs values in your MEX file. 

/*=================================================================
 * mexfunction.c 
 *
 * This example demonstrates how to use mexFunction.  It returns
 * the number of elements for each input argument, providing the 
 * function is called with the same number of output arguments
 * as input arguments.
 
 * This is a MEX-file for MATLAB.  
 * Copyright 1984-2006 The MathWorks, Inc.
 * All rights reserved.
 *=================================================================*/
/* $Revision: 1.5.6.2 $ */
#include "mex.h"
#pragma comment(lib,"libmx.lib")
//#pragma comment(lib,"libmat.lib")
#pragma comment(lib,"libmex.lib")

void
mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
    int        i;
       
    /* Examine input (right-hand-side) arguments. */
    mexPrintf("\nThere are %d right-hand-side argument(s).", nrhs);
    for (i=0; i<nrhs; i++)  {
		mexPrintf("\n\tInput Arg %i is of type:\t%s ",i,mxGetClassName(prhs[i]));
    }
    
    /* Examine output (left-hand-side) arguments. */
    mexPrintf("\n\nThere are %d left-hand-side argument(s).\n", nlhs);
    if (nlhs > nrhs)
      mexErrMsgTxt("Cannot specify more outputs than inputs.\n");
    for (i=0; i<nlhs; i++)  {
		plhs[i]=mxCreateDoubleMatrix(1,1,mxREAL);
		*mxGetPr(plhs[i])=(double)mxGetNumberOfElements(prhs[i]);
    }
}




matlab发布com组件

matlab com builder技术,把matlab开发的算法做成组件,这些独立的com对象独立于matlab的环境。
实际上com生成过程是通过matlab的c语言编译器mcc生成,mcc和mbuild命令完全实现了matlab com builder的全部功能。
使用mbuild -setup 加载安装了的编译器
然后使用deploytool (图像界面的deployment tool)选择matlab builder for .Net 选择 Generic COM component
然后往工程中加入需要的M文件或者MEX文件。
通过工具tools/build  (ctrl +B) 编译生成相应的idl 和 代码。(实际调用了mcc命令)
再通过tools/package (ctrl +P)发布com文件。
示例1 : include _idl.h 和 idl_i.c 文件
	VARIANT x,y,out1;

	HRESULT hr = CoInitialize(NULL);

	ICOMDemo1 *pImycomponentclass;
	hr = CoCreateInstance( CLSID_COMDemo1, NULL, CLSCTX_INPROC_SERVER, IID_ICOMDemo1, (void **)& pImycomponentclass);

	//
	x.vt = VT_R8;
	y.vt = VT_R8;
	
	x.dblVal = m_mul1;
	y.dblVal = m_mul2;
	//
	hr = (pImycomponentclass -> multidouble(1, &out1, x, y));
	m_result = out1.dblVal;
	//
	CoUninitialize();
完整项目: demo3


示例2:    使用import "xxx.dll" raw_interfaces_only no_namespace named_guids (自动生成.tlh文件)
	HRESULT hr = CoInitialize(NULL);

	VARIANT x, y, out1;
	try{
		ICOMDemo1Ptr pImycomponentclass;
		hr = pImycomponentclass.CreateInstance(OLESTR("COMDemo1.COMDemo1.1_0"));
		if(FAILED(hr))  _com_issue_error(hr);

		x.vt = VT_R8;
		y.vt = VT_R8;
		x.dblVal = m_mul1;
		y.dblVal = m_mul2;

		hr = (pImycomponentclass -> multidouble(1,&out1,x,y));
		m_result = out1.dblVal;
	}catch(_com_error & e)
	{
		MessageBox( e.Description().length() != 0 ? (LPCSTR) e.Description(): e.ErrorMessage());
	}
	
	//
	CoUninitialize();
完整项目:demo4

示例3:    使用后期绑定com组件
	//
	VARIANT x, y, out1;
	//
	HRESULT hr = CoInitialize(NULL);
	//
	XYDispDriver disp;
	bool res = disp.CreateObject("COMDemo1.COMDemo1");
	if (false == res) return;

	x.vt = VT_R8;
	y.vt = VT_R8;
	x.dblVal = m_mul1;
	y.dblVal = m_mul2;
	//
	disp.InvokeMethod("multidouble",1, &out1, x, y);
	m_result = out1.dblVal ;
	//
	CoUninitialize();
完整项目:http://download.csdn.net/detail/fonjames/9537997

DeployTool (C++ shared library or standalone application)



mcc -W cpplib:YYYXXXXX  -T link:lib XXXXXX.m
或者直接deployTool中选择exported function (m 文件)


依赖于mclmcrrt.lib

C/C++ API
mclmcrInitialize Initializes the MATLAB Runtime proxy library
mclInitializeApplication Set up application state shared by all MATLAB Runtime instances created in current process
mclTerminateApplication Close MATLAB Runtime-internal application state
<library>Initialize[WithHandlers] Initialize MATLAB Runtime instance associated with library
<library>Terminate Free all resources allocated by MATLAB Runtime instance associated with library

mwArray Class used to pass input/output arguments to C functions generated by MATLAB Compiler SDK
mwException Exception type used by the mwArray API and the C++ interface functions
mwString String class used by the mwArray API to pass string data as output from certain methods
mclRunMain Mechanism for creating identical wrapper code across all platforms
mclIsMCRInitialized Determine if MATLAB Runtime has been properly initialized
mclWaitForFiguresToDie Enable deployed applications to process graphics events, enabling figure windows to remain displayed
mclGetLastErrorMessage Last error message from unsuccessful function call
mclGetLogFileName Retrieve name of log file used by MATLAB Runtime
mclIsJVMEnabled Determine if MATLAB Runtime was launched with instance of Java Virtual Machine (JVM)
mclIsNoDisplaySet Determine if -nodisplay mode is enabled

示例1: http://download.csdn.net/detail/fonjames/9538010
	bool res = false;
	res = mclInitializeApplication(NULL,0);
	if(!res) MessageBox("初始化Application错误!");
	res = libmccdemo1Initialize();
	if(!res) MessageBox("初始化Lib错误!");
---
	mccdemo1();
	mclWaitForFiguresToDie(NULL);
---
	res = mclTerminateApplication();
	if(!res) MessageBox("结束程序错误!");
	libmccdemo1Terminate();


示例2: http://download.csdn.net/detail/fonjames/9538014
	// TODO: Add extra initialization here
	bool res = false;
	res = mclInitializeApplication(NULL,0);
	if(!res) MessageBox("初始化Application错误");
	res = libmccdemo2Initialize();
	if(!res) MessageBox("初始化Lib错误!");
------
	// TODO: Add your control notification handler code here
	double figsize[] = {0.0 , 0.0};
	//
	CRect client_rect;
	GetClientRect(&client_rect);
	figsize[0] = client_rect.Width();
	figsize[1] = client_rect.Height();

	//
	mwArray mwFigSize(2,1,  mxDOUBLE_CLASS, mxREAL);
	mwFigSize.SetData(figsize,2);

	//call fun
	mccdemo2(mwFigSize);

	//
	m_figure.PasteFigure();
----
	// TODO: Add your message handler code here
	bool res = mclTerminateApplication();
	if (!res) MessageBox ("结束程序错误");
	libmccdemo2Terminate();


示例3:   http://download.csdn.net/detail/fonjames/9538020
	// TODO: Add extra initialization here
	bool res = false;
	res = mclInitializeApplication(NULL,0);
	if (!res) MessageBox("初始化Application错误!");
	res = libmccdemo3Initialize();
	if (!res) MessageBox("初始化Lib错误!");
-----
	char wnd_name[] = "MyTest";

	mwArray mwWndName(wnd_name);
	mccdemo3(mwWndName);
	
	HWND hFig = ::FindWindow(NULL,wnd_name);
	while( hFig == NULL) hFig = ::FindWindow(NULL,wnd_name);
	::ShowWindow(hFig, SW_HIDE);

	CRect figure_rt;
	CWnd *myfigure = GetDlgItem(IDC_STATIC);
	myfigure->GetWindowRect(&figure_rt);
	long fig_w = figure_rt.Width();
	long fig_h = figure_rt.Height();

	::SetParent(hFig,myfigure->GetSafeHwnd());
	
	long lStyle = ::GetWindowLong(hFig,GWL_STYLE);
	::SetWindowLong(hFig, GWL_STYLE,lStyle &(~ WS_CAPTION) & (~ WS_THICKFRAME));
	::ShowWindow(hFig, SW_SHOW);

	::SetWindowPos(hFig, NULL, 0,0, fig_w+8, fig_h +33, SWP_NOZORDER|SWP_NOACTIVATE);
	::ShowWindow(hFig, SW_SHOW);

	::SetForegroundWindow(this -> m_hWnd);
----
	bool res = mclTerminateApplication();
	if(!res) MessageBox("Terminate failed");
	libmccdemo3Terminate();


使用ActiveX技术

1. matlab作为activeX自动服务器,在VC中 开启progid  “MATLAB.Application", 然后通过invoke调用matlab的函数完成计算。
	HRESULT hr;
	wchar_t progid[] = L"Matlab.Application";
	CLSID clsid;
	::CLSIDFromProgID(progid, &clsid);
	IDispatch* pIDdispatch = NULL;

	::CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&pIDdispatch);

	DISPID dispid;
	OLECHAR *name = L"Execute";
	pIDdispatch -> GetIDsOfNames(IID_NULL, &name, 1 , GetUserDefaultLCID(), &dispid);
	DISPPARAMS dispparams = { NULL, NULL, 1, 0};
	
	VARIANT para;
	para.vt = VT_BSTR;
	para.bstrVal = A2BSTR(m_Command.GetBuffer(512));

	VARIANT result;
	dispparams.rgvarg = ¶
	hr = pIDdispatch ->Invoke(dispid, //DISPID
		IID_NULL, //must be iid_null
		GetUserDefaultLCID(), DISPATCH_METHOD, //method
		&dispparams, //methods arguments
		&result, //results
		NULL, //exception
		NULL);//arguments error
	m_result = result.bstrVal;

完整代码:http://download.csdn.net/detail/fonjames/9538024

2. matlab中使用actxserver("progid"), matlab实例化其他程序,比如excel之类的。


一些基本操作API(array)


Create array of specified type, allocate and free memory

Use the mxCreate* functions to create MATLAB® arrays. Use the mxCallocmxMalloc, and mxRealloc functions to allocate dynamic memory.

You allocate memory whenever you use an mxCreate* function or when you call the mxCalloc and associated functions. Use mxDestroyArray to free memory allocated by the mxCreate* functions. Use mxFree to free memory allocated by the mxCalloc and associated functions.


C Functions
mxCreateDoubleMatrix 2-D, double-precision, floating-point array
mxCreateDoubleScalar Scalar, double-precision array initialized to specified value
mxCreateNumericMatrix 2-D numeric matrix
mxCreateNumericArray N-D numeric array
mxCreateUninitNumericMatrix Uninitialized 2-D numeric matrix
mxCreateUninitNumericArray Uninitialized N-D numeric array
mxCreateString 1-N array initialized to specified string
mxCreateCharMatrixFromStrings 2-D mxChar array initialized to specified value
mxCreateCharArray N-D mxChar array
mxCreateLogicalScalar Scalar, logical array
mxCreateLogicalMatrix 2-D logical array
mxCreateLogicalArray N-D logical array
mxCreateSparseLogicalMatrix 2-D, sparse, logical array
mxCreateSparse 2-D sparse array
mxCreateSparseLogicalMatrix 2-D, sparse, logical array
mxCreateStructMatrix 2-D structure array
mxCreateStructArray N-D structure array
mxCreateCellMatrix 2-D cell array
mxCreateCellArray N-D cell array
mxDestroyArray Free dynamic memory allocated by MXCREATE* functions
mxDuplicateArray Make deep copy of array
mxCalloc Allocate dynamic memory for array, initialized to 0, using MATLAB memory manager
mxMalloc Allocate uninitialized dynamic memory using MATLAB memory manager
mxRealloc Reallocate dynamic memory using MATLAB memory manager
mxFree Free dynamic memory allocated by mxCalloc, mxMalloc, mxRealloc, mxArrayToString, or mxArrayToUTF8String functions


版权声明:本文为博主原创文章,转载请声明链接。

Matlab和C混合编程的一个靠谱思路

Matlab和C混合编程的一个靠谱思路写在前面的话 (1)如无特殊需要(如速度),尽量不要做A语言和B语言互相转化这样的事情。 (2)如无特殊需要(如封装),尽量不要做A、B两种语言互相调用...
  • huiyuanliyan
  • huiyuanliyan
  • 2016年06月28日 10:14
  • 2785

C/C++与Matlab混合编程初探

Matlab 拥有丰富的功能,编程简单。不过,有些情况下,Matlab程序的执行速度比较慢。C/C++编译执行的程序速度比较快,编程难度上比Matlab要高一些。因此存在一种方案,就是使用Matlab...
  • bendanban
  • bendanban
  • 2014年07月15日 21:42
  • 27438

MATLAB与C/C++混合编程之MATLAB调用C程序

通过把耗时长的函数用c语言实现,并编译成mex函数可以加快执行速度。Matlab本身是不带c语言的编译器的,所以要求你的机器上已经安装有VC,BC或Watcom C中的一种。如果你在安装Matlab时...
  • sbtdkj1017
  • sbtdkj1017
  • 2007年11月25日 15:28
  • 33151

Matlab与C/C++混合编程接口及应用

http://www.cnblogs.com/lidabo/archive/2012/08/24/2654148.html   在参考文献基础上。补充和完善了。 Matlab与C/C++混合...
  • zoeyunjj
  • zoeyunjj
  • 2015年11月05日 17:36
  • 1954

matlab和c++混合编程---matlab和vs的环境配置问题

matlab调用c++代码的详细步骤已经在我的另外一篇博客中(matlab和c++混合编程---方法和步骤)说明,这里不再重复。按照它说明的步骤,mex编译一个简单的.cpp文件没有任何问题。但是如果...
  • yimiyangguang185
  • yimiyangguang185
  • 2016年09月23日 17:24
  • 1622

Matlab mex -setup 找不到编译器

Matlab mex -setup 找不到编译器在Matlab中使用mex编译使用 c/c++ ,首先要设置编译器,mex -setup.但是有时候会遇到找不到编译器的错误,错误原因有很多。我的电脑上...
  • yc461515457
  • yc461515457
  • 2016年06月11日 11:20
  • 24040

MATLAB与C/C++混合编程之MATLAB调用C程序

通过把耗时长的函数用c语言实现,并编译成mex函数可以加快执行速度。Matlab本身是不带c语言的编译器的,所以要求你的机器上已经安装有VC,BC或Watcom C中的一种。如果你在安装Matlab时...
  • Eric2016_Lv
  • Eric2016_Lv
  • 2017年04月09日 13:09
  • 812

Matlab 未找到支持的编译器或 SDK 解决方法归纳

使用Matlab需要混合编译时,Matlab编译器设置时有时会遇到如下问题 >> mbuild -setup 错误使用 mbuild (line 164) Unable to compl...
  • GSzhan
  • GSzhan
  • 2016年03月21日 22:48
  • 24781

MATLAB和VS2010的混合编程需要注意的问题

接上一篇文章吧,虽然上一篇距离现在几个月了。2015年第一发。 对于BM3D算法,在作者的主页他们给出了MATLAB的代码,在MATLAB上跑了一下,果然很好很强大,同时也跑了跑实验验证了一下linu...
  • qwopasf
  • qwopasf
  • 2015年03月20日 17:49
  • 2987

Matlab转c与c++代码

作为一个强大的科学计算软件,matlab广泛运用于较多领域,以其简单的编程风格,便利的调试环境等等众多优点,在编写算法与测试的时候通常用到。然而很多的实际运用上matlab毕竟还不是很普及,相反还是c...
  • on2way
  • on2way
  • 2015年10月17日 15:36
  • 20394
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[Matlab] matlab与C/C++混合编程汇总
举报原因:
原因补充:

(最多只允许输入30个字)