2011年7月21日星期四
cygwin 与 emacs
(1)
在没有cygwin之前,emacs中 M-x ediff 之类命令不能使用的,因为emacs找不到相应的程序。安装cygwin之后,只要把cygwin加入到PATH中,就可以使用啦。
(2)
再谈另外一个问题。
emacs中要使用cygwin提供的类unix路径表示,需要插件cygwin-mount.el,可以到emacswiki去下载。
(3)
关于使用cygwin的终端,这里是我的一点小经验。
但可能也需要在emacs中使用shell,这不是一个简单的问题。通常有三种方法,在emacs中使用shell。一种是M-x term, 使用终端模拟器;一种是M-x shell,使用 shell mode;还有一种是M-x eshell,使用 eshell mode。
M-x term 在 windows下不能运行,所以忽略不计。在linux下,配合multi-term插件,term是个很不错的选择。
shell mode 可以运行,在没有其他任何设置情况下,用的是windows自带的cmd.exe。你可能想到把它替换成cygwin带的bash.exe。是的,网上也很多这样的设置。这样设置后,在我这里,它表现的很糟糕。首先一个问题是乱码,并不是满屏乱码,而是在 ls 后总会带一些类似"~<$g["的一行很讨厌的尾巴,让人极其抓狂。第二个问题是shell mode 是个文本,所以你要用终端的那种方式去操作,刚开始会感觉到很不适应。第三个问题是中文的支持。中文显示是可以的,但是对于目录名或者文件名中有中文时,不能正确补全,甚至于都不能执行。比如 "cd 目录",就会说找不到"目录"这个路径。
或者你想不换成bash,还是用cmd。那第一个问题就不是问题,乱码在cmd下是不存在的。第二个问题是习惯问题,可以慢慢去适应。第三个问题仍然存在,很闹心。
看起来eshell是个唯一的选择,至少在windowsx下是如此。eshell是emacs自带的用elisp写的一个模式,所以它的传说中的缺点是比较慢,可能经不起大量的操作(是的,我也不知道我在说什么)。eshell也不是尽善尽美,对中文支持还是有些问题(打开有文件名有中文的文件时,中文会乱码,提示找不到该文件),但还是处在可以忍受的地步,至少"cd 目录"可以执行,以及补全也做的不错。
2011年6月26日星期日
Cygwin
安装Cygwin用的是学校的安装源,速度还算可以吧。我的环境是Win XP SP3 英文版,Language for non-unicode选了Chinese PRC。
(1) terminal的选择
没怎么用过终端,Ubuntu下自带的Gnome Terminal 都说很差劲,我倒觉得挺华丽和方便的,说明我对终端的使用程度不高,还没有培养出审美能力。
a. rxvt
推荐比较多的是用rxvt,好吧,那就用rxvt吧。配置rxvt显示中文就让我焦头烂额了一整天,结果还是没有搞好。最多只能显示中文,但是无法输入中文。我失败的配置如下:
~/.bashrc 中添加
#中文环境
#设置完可以显示中文
export LC_CTYPE=zh_CN.GB2312
export LANG=zh_CN.GB2312
#ls 显示颜色
alias ls='ls --color --show-control-chars'
网上的说法是要使rxvt能够输入中文,在~/.inputrc中添加:
set meta-flag on
set convert-meta off
set input-meta on
set output-meta on
我试过,没效果。在这上面浪费了我好多时间。不过,在 ~/.inputrc中添加
set completion-ignore-case on能使终端忽略大小写。
b. urxvt
还有个推荐说是urxvt,也就是rxvt的unicode版。在cygwin中,这是需要X 环境的。我没安装。
待实验。
c. mintty
这是我现在用的终端,是在cygwin的安装源中。无需设置,即可方便显示中文和输入中文。我让ls 显示颜色以及忽略大小写。
d. cmd
为什么不直接用cmd.exe 开 bash 呢? 也是无需设置显示中文和输入中文。但是,我不知道为什么我不用,或许是装13。
(2) Home路径设置
默认情况下,Home路径在/home/yourname,而/就是cygwin安装目录。很显然,你不会真把这个目录当作home目录,文件全存放在这吧?可以手动修改/etc/passwd文件来设置你喜欢的目录,路径格式使用cygwin风格,比如d:/tizzy目录,在此处应该为/cygdrive/d/tizzy 。
(3) 调用其他程序
居然cygwin是在windows上,说明windows上也有一些你比较顺手的程序,或者已经懒得去用cygwin中类似功能的程序。
为了能够在终端中调用,把每个程序的路径加入到PATH,我是直接加在系统PATH中。然后在目录下建个文件,起个你喜欢的名字,用来启动程序。比如:
我在widnows下用PDFXCview.exe来阅读pdf,安装路径在D:\Program Files\Tracker Software\PDF Viewer,把这个路径加入到系统PATH,在目录下建 pdfview 文件(是的,没有后缀),文件内容为
#!/bin/sh这样,就可以在终端中用pdfview 来打开pdf了。当然,你也可以不写pdfview文件,而用pdfxcview来启动,但是,这个名字很难记,是不是?!
run PDFXCview.exe "$@"
update:Jun 30,2011
本来以为上面设置就可以,后来打开pdf只能显示第一页,不知道原因。如果直接调用windows下的程序(因为已加入到PATH中),是可以正常打开,但是会占用一个终端,这是我不希望看到的。
实际上,cygwin提供了一个命令 cygstart,可以用来打开任何文件,默认会调用windows下的关联程序来打开,而且不占用终端。这正是我所需要的。
2011年6月24日星期五
MSYS 设置
I. 中文乱码解决方案
(1)ls显示中文不正常解决方法:
/etc/profile 中 添加
alias ls='ls --show-control-chars -F --color=tty'
(2)输入中文不正常解决方法:
在 /etc/inputrc.default 及 ~/.inputrc 中更改
set meta-flag on
set input-meta on
set output-meta on
set convert-meta off
II. 配置字体及颜色
可以通过C:\msys\1.0\msys.bat这个文件来修改,即安装路径下的msys.bat文件。
查找:
start rxvt -backspacekey -sl 2500 -fg %FGCOLOR% -bg %BGCOLOR% -sr -fn Courier-12 -tn msys -geometry 80×25 -e /bin/sh –login -i
字体如果使用truetype,界面会变得更丑,比如Courier New 。所以我还是老实使用默认的Courier。
III. 使用其他程序
在MSYS中提供了一些便利的unix-like工具,但你可能在windows下也有一些常用的工具,比如word,或者播放器之类的。这时可能通过编写脚本,使得在rxvt中能够直接调用这些工具。
看下面两个例子
在/bin 目录下添加/bin/splayer 文件,文件内容为:
#! /bin/sh
/d/Program\ Files/Tracker\ Software/PDF\ Viewer/pdfxcview.exe "$@"
这样,在rxvt中就可以通过 splayer 和 pdfview 调用 播放器和pdf阅读器了。
2011年5月17日星期二
WS_POPUP WS_OVERLAPPED WS_CHILD
WS_POPUP WS_OVERLAPPED WS_CHILD
Overlapped Windows
An overlapped window is a top-level window that has a title bar, border, and client area; it is meant to serve as an application's main window. It can also have a window menu, minimize and maximize buttons, and scroll bars. An overlapped window used as a main window typically includes all of these components.
By specifying the WS_OVERLAPPED or WS_OVERLAPPEDWINDOW style in the CreateWindowEx function, an application creates an overlapped window. If you use the WS_OVERLAPPED style, the window has a title bar and border. If you use the WS_OVERLAPPEDWINDOW style, the window has a title bar, sizing border, window menu, and minimize and maximize buttons.
Pop-up Windows
Pop-up windows are top-level windows and are connected to the desktop window's child windows list. Applications usually use pop-up windows for dialog boxes. The main difference between pop-up and overlapped windows is that pop-up windows need not have captions and overlapped windows must have captions. When a pop-up window does not have a caption, it can be created without a border. Pop-up windows may own other top-level windows or be owned by other top-level windows or both. All pop-up windows have the WS_CLIPSIBLINGS style, even if it was not specified. Pop-up windows must not be created with the CW_USEDEFAULT value for either the position or the size of the window. Pop-up windows that use CW_USEDEFAULT will exist but will have no size or no position or both. Overlapped windows are usually reserved for your application's main window and, in fact, are sometimes called Main windows or Frame windows. Pop-up windows are usually used to communicate with the user in the form of Dialog boxes and Message boxes.
A pop-up window is a special type of overlapped window used for dialog boxes, message boxes, and other temporary windows that appear outside an application's main window. Title bars are optional for pop-up windows; otherwise, pop-up windows are the same as overlapped windows of the WS_OVERLAPPED style.
You create a pop-up window by specifying the WS_POPUP style in CreateWindowEx. To include a title bar, specify the WS_CAPTION style. Use the WS_POPUPWINDOW style to create a pop-up window that has a border and a window menu. The WS_CAPTION style must be combined with the WS_POPUPWINDOW style to make the window menu visible.
Child Windows
Child windows must have a parent window and are confined to the client area of their parent. This is the major distinction between child windows and overlapped and pop-up windows. Child window parents can be top-level windows or other child windows. Child windows are positioned from their parent window's upper-left corner and not from the upper-left of the screen as are top-level windows. Child windows are clipped to the client area of their parent. Controls in a dialog box are child windows whose parent is the dialog box. Child windows must not be created with the CW_USEDEFAULT value for either the position or size of the window. Child windows that use CW_USEDEFAULT will exist but will have no size or position or both.
A child window has the WS_CHILD style and is confined to the client area of its parent window. An application typically uses child windows to divide the client area of a parent window into functional areas. You create a child window by specifying the WS_CHILD style in the CreateWindowEx function.
A child window must have a parent window. The parent window can be an overlapped window, a pop-up window, or even another child window. You specify the parent window when you call CreateWindowEx. If you specify the WS_CHILD style in CreateWindowEx but do not specify a parent window, the system does not create the window.
A child window has a client area but no other features, unless they are explicitly requested. An application can request a title bar, a window menu, minimize and maximize buttons, a border, and scroll bars for a child window, but a child window cannot have a menu. If the application specifies a menu handle, either when it registers the child's window class or creates the child window, the menu handle is ignored. If no border style is specified, the system creates a borderless window. An application can use borderless child windows to divide a parent window's client area while keeping the divisions invisible to the user.
2011年2月10日星期四
ShowWindow的疑问
2011年1月10日星期一
VC++ 2005 Express + SDK
Step 1: Install Visual C++ Express.
If you haven't done so already, install Visual C++ Express.
Step 2: Install the Microsoft Platform SDK.
Install the Platform SDK over the Web from the Download Center. Follow the instructions and install the SDK for the x86 platform.
Step 3: Update the Visual C++ directories in the Projects and Solutions section in the Options dialog box.
From the Tools menu in Visual Studio, select Options. The Options dialog box appears.
From the Options dialog box, expand the Projects and Solutions node and select VC++ Directories. In that section, add the following paths to the appropriate subsection:
* Executable files: C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin* Include files: C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include
* Library files: C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib
Note: Alternatively, you can update the Visual C++ Directories by modifying the VCProjectEngine.dll.express.config file located in the \vc\vcpackages subdirectory of the Visual C++ Express install location. Please make sure that you also delete the file "vccomponents.dat" located in the "%USERPROFILE%\Local Settings\Application Data\Microsoft\VCExpress\8.0" if it exists before restarting Visual C++ Express Edition.
Step 4: Update the corewin_express.vsprops file.
One more step is needed to make the Win32 template work in Visual C++ Express. You need to edit the corewin_express.vsprops file (found in C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults) and
Change the string that reads:
AdditionalDependencies="kernel32.lib"
to
AdditionalDependencies="kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib"
Step 5: Generate and build a Win32 application to test your paths.
In Visual C++ Express, the Win32 Windows Application type is disabled in the Win32 Application Wizard. To enable that type, you need to edit the file AppSettings.htm file located in the folder %ProgramFiles%\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\".
In a text editor comment out lines 441 - 444 by putting a // in front of them as shown here:
// WIN_APP.disabled = true;
// WIN_APP_LABEL.disabled = true;
// DLL_APP.disabled = true;
// DLL_APP_LABEL.disabled = true;
Save and close the file and open Visual C++ Express.
From the File menu, click New Project. In the New Project dialog box, expand the Visual C++ node in the Product Types tree and then click Win32. Click on the Win32 Console Application template and then give your project a name and click OK. In the Win32 Application Wizard dialog box, make sure that Windows application is selected as the Application type and the ATL is not selected. Click the Finish button to generate the project.
As a final step, test your project by clicking the Start button in the IDE or by pressing F5. Your Win32 application should build and run.
参考译文:
安装之后,您可以立即使用Visual C++ 2005速成版来生成功能强大的.NET Framework 应用程序。若要使用 Visual C++ 速成版生成Win32应用程序,只需采取几个步骤,下面对此进行了详细介绍。
1. 安装 Platform SDK 以便与 Visual C++ 速成版结合使用从 Platform SDK 更新站点 的 Platform SDK Update 站点通过 Web 安装 Microsoft Platform SDK。在该页上,单击“Download”(下载),然后确保从列表中依次选择“Windows SDK”和“Core SDK”。
2. 从 Visual Studio 中的“工具”菜单上,选择“选项”。出现“选项”对话框。
从“选项”对话框中,展开“项目和解决方案”节点并选择“VC++ 目录”。在该部分,将以下路径添加到相应的子节:
可执行文件:C:\Program Files\Microsoft SDK\Bin
包含文件:C:\Program Files\Microsoft SDK\include
库文件:C:\Program Files\Microsoft SDK\lib
注意 在您的系统上,Platform SDK 的位置可能有所不同。
3. 更新 corewin_express.vsprops 文件
(位于C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults 中)
并将以下字符串:
AdditionalDependencies="kernel32.lib"
更改为:
AdditionalDependencies="kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib"
注意 在您的系统上,Visual C++ 速成版 可能安装到了不同的位置。
4. 在Visual C++ 速成版,Win32应用程序向导上的Windows 应用程序选项是不可选的,要使用这个选项,你需要修改AppSettings.htm这个文件,它位于"%ProgramFiles%\ Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\".
在文本编辑器用"// "符号把文件里的441 - 444这几行注释掉,像下面这样:
// WIN_APP.disabled = true;
// WIN_APP_LABEL.disabled = true;
// DLL_APP.disabled = true;
// DLL_APP_LABEL.disabled = true;
保存和关闭文件,然后打开Visual C++ 速成版.
2011年1月8日星期六
msvcprt.lib(MSVCP90.dll) : error LNK2005:已经在libcpmtd.lib(xmutex.obj) 中定义
这篇文章要来谈谈程式库 (Library) 连结,以及关于 MSVC 与 CRT 之间的种种恩怨情仇。
如果你使用的作业系统是 Linux、Mac 或其他非 Windows 平台,你可以忽略这篇文章;如果你使用的作业系统是 Windows 平台,但没有用 Microsoft Visual Studio C++(以下简称为 MSVC)软体撰写 C++ 程式的话,这篇文章对你的帮助可能很有限;但如果你的作业系统是 Windows,而且你使用的程式整合开发环境是 MSVC 软体撰写 C++ 程式的话,这篇文章应该能够帮助你釐清一些重要的基础观念。
身为程式设计者,在学习程式设计的过程中,你是否曾经遇过某些看起来不知所云的错误讯息,却不知该如何解决?例如当你快快乐乐地写完程式,并且确认所有的程式码都能成功通过编译之后,接着执行「建置方案」(Build Solution) 的步骤,结果却跑出一堆莫名其妙的错误:
LIBCMTD.lib(mlock.obj) : error LNK2005: __lock 已在 MSVCRTD.lib(MSVCR80D.dll) 中定义过了
LIBCMTD.lib(mlock.obj) : error LNK2005: __unlock 已在 MSVCRTD.lib(MSVCR80D.dll) 中定义过了
LIBCMTD.lib(crt0.obj) : error LNK2005: _mainCRTStartup 已在 MSVCRTD.lib(crtexe.obj) 中定义过了
…………
LINK : warning LNK4098: 预设的程式库 ‘MSVCRTD’ 与其他使用的程式库冲突,请使用 /NODEFAULTLIB:library
LINK : warning LNK4098: 预设的程式库 ‘LIBCMTD’ 与其他使用的程式库冲突,请使用 /NODEFAULTLIB:library
D:\Workspace\CrtLibTest\Debug\CrtLibTest.exe : fatal error LNK1169: 找到有一或多个已定义的符号
以一般的情况来说,如果在你的程式专案中有使用某些由他人所撰写的第三方程式库或是开源专案的程式库,比较容易会发生上述的错误状况。从上述这些看似离奇而令人摸不着头绪的错误讯息中,我们大概可以猜测问题点应该在于 LIBCMTD.lib 与 MSVCRTD.lib 这两个程式库身上。但到底什么是 LIBCMTD.lib 和 MSVCRTD.lib?在我们的程式码中有使用这些程式库吗?
答案是肯定的。
熟悉 C 语言的程式设计者都知道,如果要使用 printf()、scanf() 或者 fopen() 等等 C 语言的基本 I/O 操作函式时,首先必须用 #include 语法将 stdio.h 这个标头档纳入我们的程式码中。藉由 stdio.h 中对这些 I/O 操作函式所做出的函式宣告 (function declaration),编译器 (Compiler) 才得以确认 printf、scanf 以及 fopen 等等都是合法可用的函式。
而当我们撰写的程式码经过编译器产出 OBJ 形式的档案之后,需要再经由连结器 (Linker) 的处理程序,将程式码中全部有使用到的函式定义 (function definition) 连结建置起来,才能够产生出最后的程式执行档。问题来了,我们知道 printf、scanf 以及 fopen 的函式宣告存在于 stdio.h 当中,但是这些傢伙的函式定义,也就是真正的实做程式码,究竟存放在什么地方呢?
在 C 语言的标准程式库中。
由 C 语言所制订的标准程式库,称之为「执行阶段程式库」,也就是 C Run-Time Library,通常可简称为 CRT。在 C 语言的标准程式库中,包含了一组常用的基础函式,例如 I/O 处理与字串操作程序等等,所以只要我们使用 C 语言撰写程式码,就一定要将编译完成后的程式码 OBJ 档,连结至 C 语言的执行阶段程式库,才能够产生出合法的 C 语言程式执行档。
而 CRT 并非只有单一一种版本存在。事实上,除了可以依「除错」与「释出」用途分成两个版本之外,两者又可分别衍生分出「静态连结」与「动态连结」两种形式:
静态连结:
LIBCMTD.lib(除错版本)
LIBCMT.lib
动态连结:
MSVCRTD.lib(除错版本)
MSVCRT.lib
虽然这四个 CRT 版本的用途与使用方式各不相同,但却有个共通的特点,就是它们都是满足执行绪安全需求,可在多执行绪程式码中安全使用的程式库版本。事实上,在过去 MSVC 6 的版本中,本来还有另外两个 LIBCD.lib(除错版本)与 LIBC.lib 程式库,是专门给单执行绪程式使用的 CRT 版本,但是这两个选项自 MSVC 2005 开始就从设定选项中被删除掉了,所以现在大多数程式设计者使用的都是多执行绪的 CRT 版本。
在程式库连结 (library linking) 的行为中,静态连结和动态连结的分别,在于使用静态连结时,会直接将程式库的函式定义嵌入执行档之中,而使用动态连结时,程式库的函式定义则存在于另外的独立档案,通常是 DLL 格式的档案中,然后与程式执行档一同发佈给使用者。因此在档案的尺寸上,使用动态连结的执行档档案,通常会比使用静态连结的执行档档案来得更小一些。
使用动态连结 CRT 版本的好处,是能够将经常使用到的标准程式库们独立出来,放在 Windows 的系统资料夹中,以减少我们建置出来的执行档档案尺寸。但反过来说,使用动态连结 CRT 版本的缺点也在于这些与执行档相依为命的 DLL 档案上。举例来说,如果程式以 MSVC 2005 建置出 Debug 组态的执行档,则此执行档需要有 msvcr80d.dll 存在才能顺利执行;如果是 Release 组态,则相依于 msvcr80.dll。但是如果你把相同的程式码拿到 MSVC 2008 上建置,产生出来的执行档则相依于 msvcr90d.dll 与 msvcr90.dll 两个不同的 DLL 档案。不同版本的 MSVC,都会有各自不同的相依 DLL 档案。
在 MSVC 的程式专案中,如何指定程式码要使用静态连结或者动态连结的 CRT 版本?其实很容易,只要在专案属性的「C/C++」页面中,选择「程式码产生」(Code Generation) 子页面,其中有个「执行阶段程式库」(Runtime Library) 的项目,也就是专案中用来设定 CRT 连结版本的地方。其中总共有四个选项,正好对应于上述静态连结与动态连结的四个不同程式库版本。
多执行绪侦错 (/MTd):对应 LIBCMTD.lib
多执行绪 (/MT):对应 LIBCMT.lib
多执行绪侦错 DLL (/MDd):对应 MSVCRTD.lib
多执行绪 DLL (/MD):对应 MSVCRT.lib
如果你没有做任何设定就开始建置程式的话,MSVC 的预设选项则会使用动态连结的版本。
C Runtime Library
请注意,以上只是单纯 C 语言的程式库而没有包含 C++ 语言在内。如果你的程式系统中,有包含 C++ 语言的程式码的话,那又是另外一回事了。但是在专案属性的页面中,为什么找不到相关的设定选项呢?因为 MSVC 悄悄地帮程式设计者代劳处理掉了。只要在程式码中使用 #include 语法纳入任何一个 C++ 的标头档,例如 iostream 或 fstream,MSVC 就会在连结器的运作阶段中,自动帮我们连结 C++ 的执行阶段程式库。而 C++ 的执行阶段程式库,同样可分为四个版本:
静态连结:
LIBCPMTD.lib(除错版本)
LIBCPMT.lib
动态连结:
MSVCPRTD.lib(除错版本):执行档相依于 MSVCP90D.dll
MSVCPRT.lib:执行档相依于 MSVCP90.dll
至于程式执行档使用的是静态连结或者动态连结的版本,就仰赖于 C 语言的版本设定选项了。举个例子来说,如果你撰写了一个 Debug 组态的 C++ 程式,并且保留专案原先预设的建置选项(动态连结),那么最终建置出来的程式执行档将会相依于 MSVCR90D.dll 以及 MSVCP90D.dll 两个 DLL 档案。如果将相同的程式以 Release 组态建置完成,则会相依于 MSVCR90.dll 以及 MSVCP90.dll 二者。
Standard C++ Library
刚学习程式设计的入门者,经常会在满心欢喜地完成一件程式作品并且传给其他人使用时,却发现不能在别人的电脑上启动程式,其实就是陷入了使用者电脑缺少 DLL 档案而无法执行程式的窘境。有三种方法可以解决这个令人困扰的问题:
使用者的电脑,必须先安装「Visual C++ 可转发套件」(MSVC 2008 或 MSVC 2005 )。
将所需的 DLL 档案,例如 MSVCR90D.dll 与 MSVCP90D.dll,直接附在程式的下载包当中。
以静态连结方式建置程式执行档。
当你无法确定自己的程式或别人的程式,是否相依于某些特定的 DLL 档案时,有一个非常好用的免费工具程式 Dependency Walker,可以开启 EXE 格式的执行档或者 DLL 格式的动态程式库,然后详细地条列出它们所相依的 DLL 档案。
瞭解了几种不同的 CRT 版本选项之后,回到最前面的错误讯息问题,相信各位现在应该能够很清楚地理解,原来会发生这些奇怪的错误状况,是因为程式同时连结了 LIBCMTD.lib 与 MSVCRTD.lib 所以造成函式定义版本冲突。也就是说,程式连结器已经在其中一个 CRT 的版本中找到所需的函式定义,但此时却又跳出另外一位 CRT,也给了一份相同函式的实作版本,所以连结器无法判断应该忽略谁并且选择谁。
而这个状况的发生原因,就是你的程式与程式所连结的外部程式库,使用了不同的 CRT 版本之故。例如,当你的程式使用了 Lua,自然必须连结至 Lua 的程式库 lua5.1.lib,但如果 lua5.1.lib 是以静态连结版本的 CRT 建置而成,而你的程式却是以预设选项,动态连结 CRT 来建置程式执行档的话,如此一来就会产生上述这些错误讯息了。至此,问题的答案已昭然若揭,解决方法有二种:其一是将 Lua 重新以动态连结 CRT 的方式建置出一个新的程式库,其二则是将自己的程式专案改成以静态连结 CRT 方式建置。
换个角度想,当你身为一位程式库的设计开发者,想要将自己写的东西分享给其他人,但又不想要完全开放自己撰写的程式源码时,至少可以同时提供以下四种版本的程式库,以妥善满足使用者的各种不同需求:
Debug:动态连结除错版本
Release:动态连结版本
Debug_Static:静态连结除错版本
Release_Static:静态连结版本
然而,有时候世界并不会运作得如此理想。在某些特殊的状况下,当我们使用他人所写的第三方程式库时,有时可能只拿得到其中某个特定的版本,例如 Release_Static 版本时,就很有可能会遇到程式库冲突的错误情形。此时就需要视专案的实际需求而定,可以在专案属性中指定「忽略特定程式库」(Ignore Specific Library) 这个选项,让程式码连结器忽略某些程式库,以此化解动静程式库或新旧程式库之间的恩怨冲突。
小测验:你所撰写的程式,必须连结某个以静态多执行绪 (/MT) CRT 建置而成的程式库。如果你的程式在 Debug 组态下以多执行绪侦错 (/MTd) 选项建置,是否会产生冲突?如果你的程式在 Release 组态下以多执行绪 (/MT) 选项建置,是否会产生冲突?是的话,应该如何解决?
上面的方法还是不行!会出现其他问题的。
以下是我摸索出的最新的解决方法:
首先,所有的lib文件,使用/MTd或/MT编译。Debug调试模式使用/MTd,Release模式使用/MT。
然后,在自己的程序中也使用/MTd或/MT编译。这样就不会出问题了。
三种编译链接库的方式:
(1)连接Windows库。针对Win32 API编写的应用程序,上面的方法可能带来新问题,可以忽略libcmt.lib库,即可。如果还有其他问题,再忽略相应的库。
(2)MFC静态链接。上面的方法就是针对这种链接方式的,所以没问题。
(3)MFC动态链接。没有试过,应该和(1)类似。
最后补充:如果还不行,直接加入/force:multiple编译参数吧。这次之所以没有使用它,也是为了严谨起见。
2010年8月2日星期一
一个小函数,ShowErrMsg
{
TCHAR szBuf[80];
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
MessageBox(NULL, lpMsgBuf, "系统错误", MB_OK|MB_ICONSTOP);
LocalFree(lpMsgBuf);
}