2009年4月19日星期日

液压系统仿真软件DSHplus-3.6与matlab simulink联合仿真

昨天回实验室,师弟们使用DSHplus-3.6与matlab simulink联合仿真出现问题,主要是DSHplus-3.6导出模型失败,帮忙给解决了下。
 
由于本人不是搞仿真的,对matlab也只是了解一下,所以难免有错误,不对的地方请指正。
 
软件版本:DSHplus-3.6测试版 matlab 6.5  vc++ 6.0
 
1,设置matlab:
在matlab中输入命令mex -setup ,会提示是否让matlab自己搜索编译器,选择y,然后选择编译器等等,选择 VC++ 6.0(当然首先要安装该软件)。这一步需要注意的是如果matlab是7.0的版本,好像需要把vc++ 6.0安装到C盘根目录的vs98目录下,共享文件夹COMMON也要安装到C盘根目录下,会有提示的;
注意:这一步只有执行一次即可,以后再不用执行,除非你重新安装了编译器、换了编译器或者更换了用户。
 
2,建立模型,设置DSHplus-3.6,导出模型:
DSHplus-3.6的仿真方式使用嵌入到simulink中仿真,即把在DSHplus-3.6建立的仿真模型导出成matlab可以识别的动态链接库,matlab调用这些动态链接库来仿真。导出前需要先编译模型(不知道是不是必须的,也不知道是干啥),在 "选项"中选择使用"VC++ 6.0"。
然后选择"导出",选择"matlab s-function",选择"embeded"和"cosimulation"。单击"start",会让你选择导出文件目录和文件名,例如文件夹为d:\de,文件名输入de.cpp,点击确认,看下面的信息栏,首先会编译de.cpp,这个应该是模型的核心部分,主要跟DSHplus相关,它会使用DSHplus的头文件和库;需要注意的是DSHplus自带borland c++ 5.3,这一步默认是使用borland c++编译链接的(选项里面有设置,头文件路径,编译选项,库路径等等,但是都不需要设置,默认的就好),而且可能也只能使用它编译链接,因为各编译器的库不能兼容,而DSHplus自带的库明显是borland c++ 5.3编译的,vc++无法链接。
编译的这一步一般都会没有错误。下一步是编译跟matlab的接口程序(s-fuction)部分,也就是de_dll.c文件,DSHplus会直接调用matlab的mex命令来编译,估计可能是使用 mex de_dll.c de.lib命令编译,但是因为编译模型核心部分时,没有生成de.dll的引入库de.lib,故这一步会失败,到底为啥没有生成引入库,搞不明白,一方面第一步编译模型核心部分de.dll时,是使用的borland c++,这是肯定的,不能更改,所以也就不能生成VC++使用的引入库,即使能生成,也不能直接在VC++中使用,难道是DSHplus-3.6设计的失误?
 
3,生成引入库:
DSHplus-3.6不能直接编译生成de_dll.dll,那我们只能手工生成了,在matlab下执行mex de_dll.c出现:
>> mex de_dll.c
Microsoft (R) Incremental Linker Version 6.00.8168 
Copyright (C) Microsoft Corp 1992-1998. All rights reserved. 
 
de_dll.obj  
   Creating library _lib4186.x and object _lib4186.exp 
de_dll.obj : error LNK2001: unresolved external symbol _getModuleData 
de_dll.obj : error LNK2001: unresolved external symbol _unmapModule 
de_dll.obj : error LNK2001: unresolved external symbol _mapModule 
de_dll.obj : error LNK2001: unresolved external symbol _setModuleData 
de_dll.dll : fatal error LNK1120: 4 unresolved externals 
 
  D:\MATLAB6P5\BIN\WIN32\MEX.PL: Error: Link of 'de_dll.dll' failed. 
 
??? Error using ==> mex
Unable to complete successfully
很明显,是不能链接。
执行D:\Program Files\Microsoft Visual Studio\VC98\Bin>dumpbin /exports de.dll>de.def  (VC++的目录根据安装自己更改)
de.def文件内容:
Microsoft (R) COFF Binary File Dumper Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Dump of file de.dll
File Type: DLL
  Section contains the following exports for de.dll
           0 characteristics
           0 time date stamp Thu Jan 01 08:00:00 1970
        0.00 version
           1 ordinal base
           5 number of functions
           5 number of names
    ordinal hint RVA      name
          2    0 00001CB5 _getModuleData
          3    1 000019C6 _mapModule
          4    2 00001D7D _setModuleData
          1    3 00001E47 _setOutputCallback
          5    4 00001BDE _unmapModule
  Summary
        1000 .edata
        1000 .idata
        2000 .reloc
       18000 CODE
        7000 DATA
        1000 TLS
很明显,不能链接的函数在de.dll中,所以要生成de.dll的引入库!
生成方法:
a, 执行D:\Program Files\MinGW\bin>pexports de.dll>de.def  (pexports程序在MinGW的发行包中)
生成de.def文件内容:
LIBRARY de.dll
EXPORTS
_getModuleData
_mapModule
_setModuleData
_setOutputCallback
_unmapModule
 
b,对照dumpbin /exports de.dll>de.def  生成的de.def中函数列表的ordinal项,在每个函数后加上@x,中间有一空格,x为相应函数的ordinal项。
c,去掉每个函数前面的下划线;(在使用lib.exe生成引入库时,会自动加上下划线),de.def成为如下形式:
 
LIBRARY de.dll
EXPORTS
setOutputCallback @1
getModuleData @2
mapModule @3
setModuleData @4
unmapModule @5
d,生成引入库。D:\Program Files\Microsoft Visual Studio\VC98\Bin>lib.exe /def:de.def
就生成了引入库。
 
4,生成接口dll:
在matlab下执行 mex de_dll.c de.lib    一般就OK了(需要事先把dshplus的inlcude头文件目录加入到系统环境变量的inlclude中)。
 
5,在matlab下打开de.cdl,仿真即可
 
 
注意:从上面看,可能全部使用borland c++ 5.3编译器,会自动生成引入库和自动调用mex 生成dll成功,这就需要安装borland c++ 5.3,matlab中使用mex -setup设置borland c++ 5.3为默认编译器等等。
 
附录:
 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
因为模型核心dll的导出函数是统一的,所以如果工程不改名的话(例如从dshplus导出时都选择de.cpp),则可以一直使用这个de.lib链接,如果想改名则改动de.def的第一行的de.dll到其他名字,重新生成lib即可。
 

【转帖】VC中无LIB时的DLL隐式链接,制作与VC++相符合的LIB函数符号输入库

 
 
请大家注意!这种方法只能应用于输出为C格式的__stdcall调用方式!
  1. 使用VC++的工具DUMPBIN将DLL中的导出函数表导出到一定义(.DEF)文件
  EXAMPLE:
   DUMPBIN VideoDeCoder.dll /EXPROTS /OUT:VideoDeCoder.def
  2. 将导出的.DEF文件整理为一符合.DEF个数的函数导出文件
  EXAMPLE:
   VideoDeCoder.DEF 文件内容如下
  
   Dump of file VideoDeCoder.dll
  
   File Type: DLL
  
   Section contains the following exports for VideoDeCoder.dll
  
   0 characteristics
   3D49E48F time date stamp Fri Aug 02 09:46:55 2002
   0.00 version
   1 ordinal base
   11 number of functions
   11 number of names
  
   ordinal hint RVA name
  
   1 0 00010F60 _TM_ClearDecoderBuff@4
   2 1 00010E80 _TM_CloseDecoder@4
   3 2 00010F00 _TM_DecodePicture@4
   4 3 00010ED0 _TM_DecodePictureHeader@4
   5 4 00010FD0 _TM_GetFileEnd@4
   6 5 00011030 _TM_GetUValue@4
   7 6 00011060 _TM_GetVValue@4
   8 7 00011000 _TM_GetYValue@4
   9 8 00010E10 _TM_OpenDecoder@8
   10 9 00010F30 _TM_ReturnType@4
   11 A 00010F90 _TM_SetFileEnd@8
  
   Summary
  
   2000 .data
   1000 .rdata
   1000 .reloc
   15000 .text
   按照以下方法整理:
   1>添加LIB说明
   LIBRARY "VideoDeCoder" ;"xx"为DLL名称
   DESCRIPTION "VideoDeCoder library"
   2>去掉导出函数说明端以外的内容,在LIB说明下添加 "EXPROTS" 说明导出函数
   LIBRARY "VideoDeCoder"
   DESCRIPTION "VideoDeCoder library"
   EXPORTS
   ordinal hint RVA name
  
   1 0 00010F60 _TM_ClearDecoderBuff@4
   2 1 00010E80 _TM_CloseDecoder@4
   3 2 00010F00 _TM_DecodePicture@
   4 3 00010ED0 _TM_DecodePictureH
   5 4 00010FD0 _TM_GetFileEnd@4
   6 5 00011030 _TM_GetUValue@4
   7 6 00011060 _TM_GetVValue@4
   8 7 00011000 _TM_GetYValue@4
   9 8 00010E10 _TM_OpenDecoder@8
   10 9 00010F30 _TM_ReturnType@4
   11 A 00010F90 _TM_SetFileEnd@8
   3>将所有的函数放至行首,去掉 "hint" 和 "RVA" 数据,留下函数的序号 "ordinal" ,在序号前加上 "@" 符号
   形成 "_导出函数名@参数字节和 @序号" 此种格式(__stdcall 方式调用导出的函数符号是 "函数名称@参数字节和").
   最后形成.DEF文件如下:
   LIBRARY "VideoDeCoder"
   DESCRIPTION "VideoDeCoder library"
   EXPORTS
  
   TM_ClearDecoderBuff@4 @1
   TM_CloseDecoder@4 @2
   TM_DecodePicture@4 @3
   TM_DecodePictureHeader@4 @4
   TM_GetFileEnd@4 @5
   TM_GetUValue@4 @6
   TM_GetVValue@4 @7
   TM_GetYValue@4 @8
   TM_OpenDecoder@8 @9
   TM_ReturnType@4 @10
   TM_SetFileEnd@8 @11
  3. 使用VC++的LIB工具,带/DEF:(.def文件名) /MACHINE:IX86(80X86机器),就输出符合VC++格式的的LIB文件了.
  EXAMPLE:
   LIB /DEF:VideoDeCoder.def /MACHINE:IX86
  4. 接时带上LIB文件链接;注意的是当有些动态库DUMPBIN的只有函数名,无"@nn"的参数格式,如C++Builder写的DLL,输出就只有函数名符号,链接时就会报错:
  error LNK2002:unresolved external symbol "functionname@nn"
  提示程序中引入的函数符号无法识别,这时只要将DEF文件中相应的函数名称改为functionname@nn方式,重新建立
  LIB,重新链接即可.
  这样就制作成功了符合VC调用方式的LIB了!
  参考:MSDN2000
  要值得一说的是!BORLAND C++BUILDER有一个很好的工具IMPDEF可以直接将DLL中的函数输出到.DEF文件中,只要做一点点修改就可以成为符合VC的DEF文件!
  IMPDEF xxx.def xxx.dll
  这种方法只能应用于输出为C格式的__stdcall调用方式经过我的论证有些错误!我利用Borland C++和VC++做论证,发现:
  而在C++BUILDER中!
  __cdecl的函数输出前会带一"_"
  __stdcall无特征,只输出函数名
  __fastcall函数输出前带一"@"
  都无"@nn"后缀格式!
  在VC中!
  __cdecl无特征,只输出函数名
  __stdcall的函数输出前会带一"_"后缀带"@nn"
  __fastcall函数输出前带一"@"后缀带"@nn
  只要将BC的DEF文件中函数申明格式转换为VC识别的格式就可以利用LIB工具生成LIB;要使用C分格输出(extern "C")才是必须的!而且别忘了在DEF文件中的函数申明不要带"_"啊!:)不然会出现error LNK2001的链接错误!

2009年4月12日星期日

偶记

终于,小静也结婚了,像这位能从初中一下谈恋爱到结婚的,还是第一次见到,很幸福。但中午不知是啥原因,不想吃饭,面对着山珍海味竟然吃不下,真是郁闷,大家都不想喝酒,也就没有喝,两点多就各自散了。在李村玩了一会儿直接在超市买菜去了光光家做饭吃,有,虾米丝瓜,炒香菇,辣椒豆腐皮,炒茄子,肉炒胡萝卜,肉炒芹菜。俺做了其中两样,不过比较失败,主要是因为他们吓指导的,呵呵。光光已经下定决心考博了,我暂时还没有打算,不过等空闲下来应该去海大上上自习了,憧憬中!在青岛又要少了一把酒话科技的知己实在是有些不舍,然人生漂泊,有聚有散,常事而已。临回来拿了3本路遥的《平凡的世界》,记得上次看是在初中二年级了,时间久远,只记得有郝红梅这个人,还有就是主人公烧砖窑这几段,花了晚上和一上午的时间,基本上有浏览了一遍,又共鸣了一番。想自己可能并不适合看这类书,看了总要伤心流泪,总要融入到情节里面去。
 
无意间看到漫山的桃花开了,满眼的粉红,煞是好看。不禁想起 东邪西毒 里面的"他是因为那个女人才喜欢桃花的"这句话来,不禁哑然失笑,笑那位盲武士也笑自己,不过是微笑。
 
中午睡了一觉,没想到一直到3点,本来是想出去玩的,在院子里的长凳上坐了一个小时,看庭前花开花落,迎春花正开得艳,而玉兰已是落红,樱花也开了,满山的桃红,蚂蚁也出洞了,各样蝴蝶翩翩起舞。不想又过了一年,我还要独自赶路,有时候感觉看到了前面的灯光,咫尺却又天涯。"Wars come and go, but soldiers remain."。想是自己本不喜欢不停地行走的,原来漫步,爬山,游泳,都喜欢不停的运动,一直处在行动之中,从不长时间停下来观赏周围的风景,现在发现自己更喜欢独自坐在一个地方,观察周围的事物,思考自己的所为与思想,只有处在宁静的状态之中才能到达心灵的深处,才能荡尽内心的垃圾,但这样会孤独。可能另一种方式是邀一知己(也许生命的另一半更好),相坐而不言语,观风景而达禅定。
 
现在感觉到了,人与人之间,特别是男人与女人之间,很像是刺猬,离得近了可以彼此取暖而太近却又会刺伤对方。原来我是宁可别人伤害我,也不愿伤害别人,现在好像是首先不想自己被伤害,也许是受过的伤害太多吧,有很多东西都是有原因的,也是很难控制的。凡是自由应该以不伤害别人为准。
 
想我这种人,想找到人生一伴侣实在是小概率事件,不用说样子有点有伤市容,没钱没才没脑子,偏偏又是个理想主义者,感觉可遇而不可求,非得半年、几年才能产生感情,靠原始点的感觉定夺吧,理性又不允许,介绍对象对俺基本上就是一不靠谱的事。思想超前又中庸,性格外向又腼腆,内心自卑又骄傲,心灵君子又"禽兽",智商中上又阿甘,思维自由又保守,胸有大志又无所作为,喜欢有才的又喜欢漂亮的.....
 
时间到,暂停胡扯。

2009年4月2日星期四

代码

花了不到两个月时间写了大约2万多行代码,虽然因为时间要求紧,代码有很多地方很臃肿,但是已经很不错了。第一次写这么大的代码,进展还算是很顺利。喘下气