产生的DLL (VS2005, MATLAB7.5, mwArray)

from: http://www.simwe.com/forum/thread-801187-1-1.html

程序中使用MATLAB编译产生的DLL (VS2005, MATLAB7.5, mwArray)

最近有几个帖子都在讨论有关在C++程序中使用MATLAB编译产生的动态链接库DLL。本 来想用原来帖子中给出的m代码作为例子,无奈那段代码其实无法执行。为了避免分散注意力,也为了更好地讨论问题,于是决定还是另外新开一个主题,以简单的 例子,和大家一起讨论如何在C++程序中使用matlab编译产生的DLL。

同时MATLAB最新版本R2007b刚刚发布不久,其中包含编译器4.7版,有了一些新的特性,于是也借这个例子来验证一下相关的技术有没有发生大的变化。

最近讨论的问题是关于在C++程序中调用MATLAB编译产生的动态链接库。具体的问题是在 调用DLL中函数时传递参数。我们知道,MATLAB可以把m代码编译成两种DLL,分别是C语言接口和C++语言接口的DLL。论坛上的问题是关于调用 C++接口的DLL中的函数,所以这里我们就以这种DLL为例来介绍。在C++接口的DLL中,函数的输入、输出参数都是mwArray对象。所以问题归 结为如何在C++程序中使用mwArray。

这个问题本来可以只用一个简单的C++程序来练习,而不需要MATLAB编译的DLL。不过为了模拟实际情况,选择以一个更为接近实际的m代码作为例子。在这个例子中,输入输出都是矩阵,至于标量,它也是一个一行、一列的矩阵。

实验环境:Windows 2003 Std Server with SP2 (En),MATLAB R2007b,Visual Studio 2005。MATLAB安装路径:h:MATLABR2007b。

实验内容:把一个简单的m代码编译成C++接口的DLL,然后在C++程序中调用。为了简单起见,这里的C++程序是一个Win32 Console程序,而不是Windows图形界面的程序,不过不妨碍我们的讨论。

下面是这个例子用到的m代码。它定义了一个名为myadd2的函数:

[Copy to clipboard] [ - ]

CODE:

function [y,z] = myadd2(a, b)

% dummy function, just to demonstrate the idea

y = a+b;

z = a+2*b;

end

首先把这个函数编译成C++接口的DLL。为此,我们需要先设置MATLAB编译器。具体做法是在MATLAB命令行执行“mbuild -setup”。然后用下面这行命令把myadd2函数编译成一个C++接口的DLL:

[Copy to clipboard] [ - ]

CODE:

mcc -W cpplib:libmyadd2 -T link:lib myadd2

结果,我们将会得到包含libmyadd2.dll,libmyadd2.ctf,libmyadd2.h,libmyadd2.lib等在内的一些文件。接下来我们只需要这四个文件。请注意:在MATLAB R2007b之前,这些文件都会在和编译

的m代码所在的目录中,而在MATLAB R2007b,缺省情况下这些文件会在Documents and Settings中用户的My Documents目录中。

此时,打开libmyadd2.h看看,在文件的最下面我们可以发现C++接口的函数定义。仔细观察过后,我们可以发现,这个接口函数的参数是按照这样的顺序定义的:输出参数的个数、输出参数、以及输入参数。

然后在VS2005中创建一个Win32 Console的VC++工程,我在测试时取名为testmyadd2_r2007b。把以上四个文件拷贝到VC++工程的源代码所在目录。

接下来设置VC++,让它能找到MATLAB接口函数的定义及连接库函数。可以有两种设置方式:一种是改VS2005中关于VC++的设置,这样的好处是每个新的工程都能自动获得这个设定;而另一种是只改当前工程的设置,也就是设置只对该工程有效。这里用后一种方式。

在VS2005中打开工程testmyadd2_r2007b,选择菜单“Project-->Properties,在出来的对话框上,把MATLAB提供的include路径加到VC++的头文件搜索路径。如图所示:

 

 vs2005_matlabr2007b_inc01.gif (25.26 KB)

 

然后把相应的lib所在目录加到linker的额外搜索路径上。如图所示:
 vs2005_matlabr2007b_lib01.gif (25.99 KB) 

点击在新窗口查看全图
接下来,告诉VC++,我们的这个程序需要连接到另外两个额外的库函数:libmyadd2.lib和mclmcrrt.lib。中间用空格隔开。如图所示:
 vs2005_matlabr2007b_lib02.gif (23.16 KB) 

点击在新窗口查看全图
最后则是程序代码。这个程序只有一个main函数,其完整代码附在下面给大家参考。欢迎大家拍砖。谢谢!

CODE:
#include "stdafx.h"

#include 
#include "mclmcr.h"
#include "mclcppclass.h"
#include "libmyadd2.h"


int _tmain(int argc, _TCHAR* argv[])
{

       std::cout << "Hello world!" << std::endl;
       /* Initialize the MCR */ 
       if( !mclInitializeApplication(NULL,0) ) 
       { 
            std::cout << "Could not initialize the application!" << std::endl;
            return -1; 
       } 

       // initialize lib
       if( !libmyadd2Initialize())
       {
            std::cout << "Could not initialize libmyadd2!" << std::endl;
            return -1; 
       }

       try
       {
       // declare and initialize a
       mwArray a(2, 2,   mxDOUBLE_CLASS);
       double *aData;
       aData = new double[4];
       int i;
       for( i=0; i<4; ++i)
       {
            aData[i] = 1.0*i;
       }
       // print output
       std::cout << "a = " << std::endl;
       std::cout << aData[0] << ", " << aData[1] << std::endl;
       std::cout << aData[2] << ", " << aData[3] << std::endl;

       a.SetData(aData, 4);

       // declare and initialize b
       mwArray b(2, 2,   mxDOUBLE_CLASS);
       b(1,1) = 11.;
       b(1,2) = 12.;
       b(2,1) = 21.;
       b(2,2) = 22.;

       mwArray y(2, 2,   mxDOUBLE_CLASS);
       mwArray z(2, 2,   mxDOUBLE_CLASS);

       // call the function
            myadd2(2, y, z, a, b);

       // copy data from mwArray to C++ objects

       // allocate outputs
       double *yData, *zData;
       yData = new double[4];
       if( yData == NULL )
       {
            std::cout << "Failed to allocate memory for yData!" << std::endl;
            return -1;
       }

       zData = new double[4];
       if( zData == NULL )
       {
            std::cout << "Failed to allocate memory for zData!" << std::endl;
            return -1;
       }

       // copy data from mwArray to C++
       y.GetData(yData, 4);
       z.GetData(zData, 4);

       // print output
       std::cout << "y = " << std::endl;
       std::cout << yData[0] << ", " << yData[1] << std::endl;
       std::cout << yData[2] << ", " << yData[3] << std::endl;

       std::cout << "z = " << std::endl;
       std::cout << zData[0] << ", " << zData[1] << std::endl;
       std::cout << zData[2] << ", " << zData[3] << std::endl;

      
       // deallocate memory
       delete [] aData;
       delete [] zData;
       delete [] yData;
       }
       catch( const mwException& e)
       {
      std::cerr << e.what() << std::endl;
               
       }
       // terminate the lib
       libmyadd2Terminate();

       // terminate MCR
       mclTerminateApplication();


       return 0;
}
2007-10-6 23:18
 vs2005_matlabr2007b_result.gif (9.26 KB) 

点击在新窗口查看全图

实验的结果表明,在C++程序中使用MATLAB编译产生的C++接口DLL非常容易。 mwArray也很容易使用。另外,最新的MATLAB R2007b中关于这部分并没有什么大的变化。这个练习适合MATLAB 7.0以后直到MATLAB R2007b的所有版本。

ask:

就我个人6.5混编的经验,我很少弄DLL,直接编译M文件为cpp,h文件即可,VC工程中引用,按.h文件格式调用即可。

这样混编基本没有任何难度,将MATLAB程序看成MFC一个类即可,看看extern里面

相关头文件的定义,跟看MSDN一样。

抛开mclTerminateApplication();这些,这应该是一个通用的办法

手头只有6.5,不知道7.5还能生成cpp么?

answer:
从matlab7.0开始,其编译器的功能就和以前版本不一样了。它不再把m代码翻译成C/C++源代码,而是对m代码作个简单的 wrapper,通常以动态链接库的形式提供给用户以方便用户在其他的程序中使用。所以,在matlab 7.x,编译m代码不能得到以前那种意义的C/C++源程序。

不过,仅从软件开发的角度来看,我觉得用DLL来打包更为方便。如果m函数的接口不变,那么每次改变m代码后,我们只需重新编译m代码,获得新的DLL及CTF,而不需要重新编译VC客户程序。这在开发大型软件时有很大的优越性。

多谢taohe的文章,我想问一下,ctf文件是干嘛用的,谢谢,记得matlab 6.5版里面编译为DLL时没这个东西啊。

这是matlab7.0以后matlab编译器的新特性。它和旧版技术不兼容。ctf其实就是一个zip文件,其中包含加密或者说编码过的一些m代码。其中有你自己的代码,以及matlab编译器通过分析你的代码根据依赖关系找到的其他一些m代码。

转载于:https://www.cnblogs.com/mfryf/archive/2012/02/16/2354285.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

构建和测试JSF.next

JSF 2.3专家组正在努力确定哪些功能将成为即将发布的版本的一部分。 JSF团队一直在努力改善CDI的一致性。 JSF 2.3代码库中已经有许多新功能可以开始测试。 我将尝试使本文保持最新状态&#xff0c;并添加最新功能。 有关最新参考&#xff0c;请参阅Manfred的博客。 要参考Manf…

启动LINUX下的TFTP服务器

第一步: 我们要确认,LINUX下是不是安装了TFTP-SERVER. 在LINUX下输入: rpm -q tftp-server 如出现如下回复: tftp-server-0.39-2 则表示tftp-server已安装. 第二步: 修改TFTP启动脚本: 方法一: 需要修改ftptpd的启动脚本vi /etc/xinetd.d/tftp加上 disable no 此时即可启动tf…

npm 常用指令

npm install <name>安装nodejs的依赖包 例如npm install express 就会默认安装express的最新版本&#xff0c;也可以通过在后面加版本号的方式安装指定版本&#xff0c;如npm install express3.0.6 npm install <name> -g 将包安装到全局环境中 对应的的是 pac…

简单代码生成器原理剖析(一)

上篇文章&#xff08;深入浅出三层架构&#xff09;分析了简单三层架构的实现。包括Model,DAL&#xff08;数据访问层&#xff09;,BLL&#xff08;业务逻辑层&#xff09;的实现。 实际开发中&#xff0c;由于重复代码的操作&#xff0c;会花费大量时间&#xff0c;如果以代码…

Qt学习之路(4):初探信号槽

看过了简单的Hello, world! 之后&#xff0c;下面来看看Qt最引以为豪的信号槽机制&#xff01;所谓信号槽&#xff0c;简单来说&#xff0c;就像是插销一样&#xff1a;一个插头和一个插座。怎么说呢&#xff1f;当某种事件发生之后&#xff0c;比如&#xff0c;点击了一下鼠标…

当字符串为空但不为空时

介绍 我团队中的一名初级程序员遇到了一个有趣的错误。 我已经不止一次看到它的症状。 这篇文章是寻找什么以及将来如何防止它。 我还将探讨该问题的不同解决方案。 病征 有问题的代码看起来做得不错。&#xff1a; if(trouble ! null && !trouble.isEmpty()) { Syst…

注解的力量 -----Spring 2.5 JPA hibernate 使用方法的点滴整理(六): 一些常用的数据库 注解...

一、 实体 Bean 每个持久化POJO类都是一个实体Bean, 通过在类的定义中使用 Entity 注解来进行声明。 声明实体Bean Entitypublic class Flight implements Serializable { Long id; Id public Long getId() { return id; } public void setId(Long id) { this.id id; }} E…

SWT鼠标单击实现

最近&#xff0c;我做了一些SWT定制小部件的开发&#xff0c;偶然发现了一个问题&#xff0c; 为什么没有默认的SWT鼠标单击侦听器&#xff1f; 由于这个主题有时会提出&#xff0c;所以我认为写一两句话来说明背后的理性基础以及如何实现鼠标单击通常不会受到伤害。 SWT鼠标请…

第三周进度总结

本周大部分时间花费在了考驾照上&#xff0c;所以没有在学习上用太多的时间。在不多的时间里看完了老师推荐的《大道至简》这本书&#xff0c;从书中学到了很多编程方面的思想&#xff0c;受益匪浅。还完成了2个代码的编译&#xff0c;一个是判断AB和C的关系&#xff0c;这个并…

页面中插入视频的方法---video/embed/iframe总结

1. video标签 当前主流的方法当然是HTML5中的video标签了&#xff0c;但是 当前&#xff0c;video 元素只支持三种视频格式&#xff1a; Ogg 带有 Theora 视频编码和 Vorbis 音频编码的 Ogg 文件 MPEG4 带有 H.264 视频编码和 AAC 音频编码的 MPEG 4 文件 WebM 带有 VP…

Spring请求级备忘录

介绍 记忆化是一种方法级别的缓存技术&#xff0c;用于加快连续调用的速度。 这篇文章将演示如何仅使用Spring AOP实现任何数据源的请求级可重复读取。 Spring缓存 Spring提供了非常有用的缓存抽象 &#xff0c;允许您将应用程序逻辑与缓存实现细节分离。 Spring Caching使用…

从一个帖子看 所谓“知乎” 的真实水平

帖子地址&#xff1a;https://www.zhihu.com/question/27535713 明末尤其是崇祯后期&#xff0c;最大的背景是天灾瘟疫反复肆虐&#xff0c;三成人死于饥荒&#xff0c;三成人死于瘟疫&#xff0c;四成为生存从贼是当时中原的真实写照。 抛开这个最大前提不谈&#xff0c;去乱弹…

新的开始,新的挑战

我承认&#xff0c;我还比较年轻&#xff0c;我承认&#xff0c;我的经验很少&#xff0c;我承认&#xff0c;我的能力还是比较小。。。。。。 但是&#xff0c;我不怕&#xff0c;我敢往前走&#xff0c;错了我就改&#xff0c;不行我就努力&#xff0c; 要么痛苦的坚持到游戏…

响应式布局笔记

一. 布局设计 固定布局&#xff1a;以像素作为页面的基本单位&#xff0c;不管设备屏幕及浏览器宽度&#xff0c;只设计一套尺寸&#xff1b; 可切换的固定布局&#xff1a;同样以像素作为页面单位&#xff0c;参考主流设备尺寸&#xff0c;设计几套不同宽度的布局。通过设别的…

麦冬

麦冬 中文学名&#xff1a;麦冬 拉丁学名&#xff1a;Ophiopogon japonicus (Linn. f.) Ker-Gawl. 别称&#xff1a;麦门冬、沿阶草 植物界百合科 主要价值&#xff1a; 1、有养阴润肺、益胃生津、清心除烦的功效&#xff0c;用于肺燥干咳、阴虚痨嗽、喉痹咽痛、津伤口渴、…

如何使用Callable和FutureTask

介绍 从Java 1.5开始&#xff0c;在java.util.concurrent下有了新的对象集。 该程序包具有许多不同的类&#xff0c;包括线程队列。 当我用Java 1.2编程时&#xff0c;我本可以使用那些&#xff01; 当我开始看这些新玩具时&#xff0c;我变得犹豫不决。 这是什么可调用的东西&…

NodeJS的安装与使用

Node.js 就是运行在服务端的 JavaScript。越来越多的人在使用它&#xff0c;通过他我们可以用JavaScript来构建后台。对于前端程序员而言&#xff0c;不言而喻这是一条多么令人振奋的消息。对于后台程序员而言&#xff0c;这也是一种很不错的选择。 下面我就来讲解下nodejs的安…

转载 300年前的黑色“巫女”

1741年&#xff0c;北极。 白令招呼水手们把船靠上小岛的时候&#xff0c;一排黑色的鸬鹚站在陡峭的悬崖上&#xff0c;像一群黑色的巫女&#xff0c;一动不动朝着他们张望。白令顿时有了一种不祥的预兆。 果然&#xff0c;刚刚上岛&#xff0c;就遭到古怪的兰狐的袭击&#xf…

华为在爱尔兰增设150个LTE研发职位

据国外媒体报道中国电信和网络跨国公司华为技术预计将在未来两年内在爱尔兰增设150个职位。华为公司目前设在爱尔兰都柏林、阿斯隆和科克的业务处共有50名员工。现在&#xff0c;公司已经投标竞购牌照&#xff0c;目的是为在爱尔兰推出第四代宽带进行基础设施开发。华为公司爱尔…

Java EE 7 / JAX-RS 2.0 – REST上的CORS

Java EE REST应用程序通常在开箱即用的开发机器上运行良好&#xff0c;该开发机器上所有服务器端资源和客户端UI均指向“ localhost”或127.0.0.1。 但是&#xff0c;当涉及跨域部署时&#xff08;当REST客户端不再与托管REST API的服务器位于同一域时&#xff09;&#xff0c;…