CODE大全
版权声明:本文为博主原创文章,未经博主允许不得转载。

DuiLib 静态库编译方法

发布时间:『 2017-07-31 16:52』  博客类别:编程语言  阅读(2188) 评论(0)

Duilib 是一款强大的界面开发工具,可以将用户界面和处理逻辑彻底分离,极大地提高用户界面的开发效率。

学习 Duilib 首先需要从它的源码编译学起,本文将详细的介绍如何对 Duilib 的静态库源码进行编译。

添加官方 DuiLib_Static 项目

在官方的代码中有一个 DuiLib_Static.vcxproj 的工程文件,这就是 DuiLib 的静态库编译的工程。

DuiLib_Static.vcxproj 的工程文件

但是细心的人可能发现了,仅有一个 .vcproj 的项目文件,没有 .filters 的文件目录树描述文件。没关系,我们直接复制一份 Duilib.vcxproj.filters 文件改名为 Duilib_Static.vcxproj.filters 即可,这个文件只是描述在 vs 中看到的文件目录结构,静态库和动态库都使用一样的目录树即可。修改完成后是下面这幅图的样子:

Duilib 文件目录结构

我们增加了 Duilib_Static.vcxproj.filters 的文件,此时我们把这个工程添加到 duilib 的解决方案中。

duilib的解决方案

选择 Duilib_Static 项目然后点击添加。

Duilib_Static 项目

添加完成后我们就能看到 Duilib_Static 的项目在 DuiLib 的解决方案中了,而且目录树结构完整。 

DuiLib 的解决方案

此时我们选择 UnicodeDebug 的版本编译一个静态库来进行一下测试,注意如果你的测试程序是多字节的这里也要编译成多字节的版本,否则链接是会出错。

1>------ 已启动生成:  项目: DuiLib_Static, 配置: UnicodeDebug Win32 ------
1>  StdAfx.cpp
1>  UIWebBrowser.cpp
1>  UITreeView.cpp
1>  UIText.cpp
1>  UISlider.cpp
1>  UIScrollBar.cpp
1>  UIRichEdit.cpp
1>  UIProgress.cpp
1>  UIOption.cpp
1>  UIList.cpp
1>  UILabel.cpp
1>  UIGifAnim.cpp
1>  UIEdit.cpp
1>  UIDateTime.cpp
1>  UICombo.cpp
1>  UICheckBox.cpp
1>  UIButton.cpp
1>  UIActiveX.cpp
1>  UIVerticalLayout.cpp
1>  UITileLayout.cpp
1>  UITabLayout.cpp
1>  正在生成代码...
1>  正在编译...
1>  UIHorizontalLayout.cpp
1>  UIChildLayout.cpp
1>  UIRender.cpp
1>  UIMarkup.cpp
1>  UIManager.cpp
1>  UIDlgBuilder.cpp
1>  UIControl.cpp
1>  UIContainer.cpp
1>  UIBase.cpp
1>  Utils.cpp
1>  UIDelegate.cpp
1>  WinImplBase.cpp
1>  UIlib.cpp
1>  正在生成代码...
1>  stb_image.c
1>  XUnzip.cpp
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppBuild.targets(1361,5): 
warning MSB8012: TargetPath(d:\Documents\Code\DuiLib\DuiLib\.\Build\Debug_u\DuiLib_Static.lib) does not match the Library's 
OutputFile property value (d:\Documents\Code\DuiLib\DuiLib\Build\Debug_u\DuiLib_Static_ud.lib). This may cause your project 
to build incorrectly. To correct this, please make sure that $(OutDir), $(TargetName) and $(TargetExt) property 
values match the value specified in %(Lib.OutputFile).
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppBuild.targets(1363,5): warning MSB8012: 
TargetName(DuiLib_Static) does not match the Library's OutputFile property value (DuiLib_Static_ud). 
This may cause your project to build incorrectly. To correct this, please make sure that $(OutDir), 
$(TargetName) and $(TargetExt) property values match the value specified in %(Lib.OutputFile).
1>  DuiLib_Static.vcxproj -> d:\Documents\Code\DuiLib\DuiLib\.\Build\Debug_u\DuiLib_Static.lib
========== 生成:  成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

项目成功生成了(以上操作我已经提交 PR 给 duilib 官方,是否合并要看他们了),生成的静态库在 DuiLib\Build\Debug_u 目录下,接下来我们新建一个项目来引入 DuiLib 静态库。

DuiLib 静态库

新建测试项目

在你新建项目的时候,也有一些注意点,我们一步一步介绍,然后重要的关键点跟大家强调一下就可以了。

首先我们新建一个 Win32 项目取名为 DuilibTest,要注意的是,Win32 项目要选择引用 ATL 库

Duilib 项目

否则编译的时候会提示如下错误:

error C2504: “VARIANT”: 未定义基类
error C2061: 语法错误: 标识符“LPOLESTR”
error C2535: “DuiLib::CVariant::CVariant(void)”: 已经定义或声明成员函数
...

如果你的工程已经建立好了,想引入 ATL,那么直接在 stdafx.h 中添加下面三行代码就可以了,但记得要在引入 DuiLib 头文件之前。

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
#include <atlbase.h>
#include <atlstr.h>

新建好项目以后我们来清理一下无用代码,打开 DuilibTest.cpp 文件,删除一些无用的代码,最终清理后的代码如下:

// DuilibTest.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "DuilibTest.h"

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	return 0;
}

简单几行实现了一个 WinMain 函数,然后我们来引入 Duilib 的头文件,首先右键 DuilibTest 项目属性。首先选择 VC++目录->包含目录,里面添加上 duilib 的头文件路径。如下图所示:

duilib 的头文件路径

然后打开 常规->平台工具集,官方目前 github 上的版本是 VS2013 支持 XP,我们的测试项目也要与编译静态库时选择的这个平台工具集一样。

编译静态库

确定后打开 连接器->常规->附加库目录,将 DuiLib 生成的静态库目录添加进去(这里只为做演示,真正项目自己规划这个目录的结构)

DuiLib 生成的静态库

确定后再打开 链接器->输入->附加依赖库,将 DuiLib_Static_ud.lib 添加到附加依赖库列表中。

DuiLib_Static_ud.lib 添加到附加依赖库

最后再打开 C/C++->预处理器->预处理器定义,将 UILIB_STATIC 的宏添加进去,这相当于我们在代码中 #define UILIB_STATIC

 C/C++->预处理器->预处理器定义

至此差不多了,我们添加一些测试代码(代码来自 Alberl),如下:

// DuilibTest.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "DuilibTest.h"
#include "UIlib.h"

using namespace DuiLib;

class CDuiFrameWnd : public CWindowWnd, public INotifyUI
{
public:
	virtual LPCTSTR GetWindowClassName() const { return _T("DUIMainFrame"); }
	virtual void    Notify(TNotifyUI& msg) {}

	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		LRESULT lRes = 0;

		if (uMsg == WM_CREATE)
		{
			CControlUI *pWnd = new CButtonUI;
			pWnd->SetText(_T("Hello World"));   // 设置文字
			pWnd->SetBkColor(0xFF00FF00);       // 设置背景色

			m_PaintManager.Init(m_hWnd);
			m_PaintManager.AttachDialog(pWnd);
			return lRes;
		}

		if (m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes))
		{
			return lRes;
		}

		return __super::HandleMessage(uMsg, wParam, lParam);
	}

protected:
	CPaintManagerUI m_PaintManager;
};

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	CPaintManagerUI::SetInstance(hInstance);

	CDuiFrameWnd duiFrame;
	duiFrame.Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
	duiFrame.ShowModal();
	return 0;
}

代码添加完成后我们编译一下程序,你可能会收到如下错误:

1>------ 已启动生成:  项目: DuiLibTest, 配置: Debug Win32 ------
1>  stdafx.cpp
1>  DuiLibTest.cpp
1>DuiLib_Static_ud.lib(UIManager.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(UIBase.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(UIControl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(UIButton.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(StdAfx.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(Utils.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(UIDelegate.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(UIRender.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(UIRichEdit.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(UILabel.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(UIContainer.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>DuiLib_Static_ud.lib(UIScrollBar.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项:  值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(DuiLibTest.obj 中)
1>LINK : warning LNK4098: 默认库“LIBCMTD”与其他库的使用冲突;请使用 /NODEFAULTLIB:library
1>d:\Documents\Visual Studio 2013\Projects\DuilibTest\Debug\DuiLibTest.exe : fatal error LNK1319: 检测到 12 个不匹配项
========== 生成:  成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

这是因为我们静态库编译时选择的代码生成时运行库不一样,依次打开 C/C++->代码生成->运行库,在 DuiLib_Static 的项目中,Unicode_Debug 版本这里的运行库选择的是 多线程调试 (/MTd),所以我们测试程序也要选择成一样的 多线程调试 (/MTd)。

多线程调试 (/MTd)

顺利的话,你再次编译一下程序,就可以正常编译通过了。

1>------ 已启动生成:  项目: DuiLibTest, 配置: Debug Win32 ------
1>  stdafx.cpp
1>  DuiLibTest.cpp
1>  DuiLibTest.vcxproj -> d:\Documents\Visual Studio 2013\Projects\DuilibTest\Debug\DuiLibTest.exe
========== 生成:  成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

如果你遇到了其他错误,请一定要按上面的几个步骤仔细核对。

总结

  • 添加静态库工程的时候记得自己拷贝一份 DuiLib_Static.vcxproj.filters。

  • 新建的工程编码方式一定要与 DuiLib 的编码一致,DuiLib 中名字为 Unicode_Debug 的配置才是支持 Unicode 的版本,别搞错了。

  • 新建的工程要选择 ATL 支持。

  • 新建的工程平台工具集要与 DuiLib 编译的静态库保持一致。

  • 新建的工程添加 链接器->输入->附加依赖项 时也要对准是不是对应的多字节/ Unicode 或 Debug/Release 版本,如果没有对准,则会提示无法链接到 DuiLib 里面的一些函数。这个一定要注意。

  • 新建的工程一定要在预处理器->预处理器定义中增加 UILIB_STATIC。

  • 新建的工程 代码生成->运行库 也一定要与 DuiLib 保持一致。


——— 全文完 ———
如有版权问题,请联系532009913@qq.com。
关键字:   DuiLib     编译     C++  
评论信息
暂无评论
发表评论
验证码: 
Powered by CODE大全 | 鄂ICP备14009759号-2 | 网站留言 Copyright © 2014-2016 CODE大全 版权所有