创建接口工程——链接库工程和测试工程 基于vs2013 & QtCreator

1、背景

因为很多情况下,我们是不给别人或者甲方爸爸源码的,所以就要将源码编译成动态或者静态链接库来调用。在windows下面开发,当然用vs是最方便的了,虽然在linux下有了vs code,但是小白表示还没有摸索明白各种环境设置是怎么回事,不如windows下面的vs来的可视化好。所以,先看看windows下开发C++的一个超级小白简单的例子,如何建立链接库工程,生成动态链接库,然后如何建立测试这个链接库的测试工程;以及如果不在同一解决方案下建立测试工程,如何从外部测试这个动态链接库。

2、vs创建工程

2.1、创建链接库工程

(1)创建

打开vs2013,选择“New Project”,在弹出的对话框中选择“Win32 project”或者“Win32 console application”。注意不要选则“Static(Windows Store apps)” 或者“DLL(Windows Store apps)”。

选择好工程的路径,取名字,默认勾选“Create directory for solution”, 点击OK。

接下来的对话框,选择“Next”。

接下来注意啦!在Application Setting这一页中,Application type这里选择“DLL”。至于下面Additional options,我当时选了“export symbols”,没选这个好像也没有少了啥(myDll)。。。,如果选择“empty project”就是一个完全空的工程,不包含任何文件。其它保持默认,点击“Finish”。

我创建的库工程叫做simpleDLL2,结构如下所示:

其中,vs自动创建的文件用红框标注了。

stdafx.h,stdafx.cpp-----(来自百度百科):英文全称为:Standard Application Framework Extensions(标准应用程序框架的扩展)。头文件预编译,就是把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、Afxwin.H)预先编译,以后该工程编译时,不再编译这部分头文件,仅仅使用预编译的结果。这样可以加快编译速度,节省时间。

因为我不用MFC,所以这个应该是可以删掉的。

targetver.h-----定义程序运行的环境。

simpleDll2.h, simpleDll2.cpp-----vs为工程创建的,这里可以理解为接口代码写在这里。后面贴代码分析。

dllmain.cpp 里面放了dll的入口函数。目前不知道这个具体有啥用,网上查了有的说是起到初始化作用。反正我没有用到,不知道删了这个cpp可以不?反正我把入口函数全部注释掉,编译后测试仍然正确。

interior.h,interior.cpp----我自己创建的新的类,希望将一些内部函数放在这里,不希望别人看到源码。

(2)结构及源码

下面具体说说这个project的结构。我们希望将所有接口函数的实现放在simpleDll2.cpp中,这个里面的接口函数调用其它cpp比如interior.cpp中的函数实现具体的功能。当编译完成时,我们可以将接口的cpp和h文件以及lib和dll给用户,而interior源码不给,保留了自己的核心技术。

首先放上simpleDll2.h:

// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the SIMPLEDLL2_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// SIMPLEDLL2_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported. 
//上面这么多话,意思就是如果你想当可输出接口函数或者类或者结构体啥的,前面加上SIMPLEDLL2_API
#ifdef SIMPLEDLL2_EXPORTS
#define SIMPLEDLL2_API __declspec(dllexport)
#else
#define SIMPLEDLL2_API __declspec(dllimport)
#endif

// This class is exported from the simpleDll2.dll
class SIMPLEDLL2_API CsimpleDll2 {
public:
	CsimpleDll2(void);
	// TODO: add your methods here.
	int extfun1(int x, int y); //在这个可输出类里定义了一个接口函数
};

extern SIMPLEDLL2_API int nsimpleDll2;
SIMPLEDLL2_API int fnsimpleDll2(void);
extern SIMPLEDLL2_API int extFun2(int x, int y, int z);  //定义了一个接口函数

然后是:simpleDll2.cpp。看见没,其实vs人家给出了可输出的变量、函数、类的例子。

// simpleDll2.cpp : Defines the exported functions for the DLL application.

#include "stdafx.h"
#include "simpleDll2.h"
#include "interior.h"

// This is an example of an exported variable
SIMPLEDLL2_API int nsimpleDll2=0;

// This is an example of an exported function.
SIMPLEDLL2_API int fnsimpleDll2(void)
{
	return 42;
}

// This is the constructor of a class that has been exported.
// see simpleDll2.h for the class definition
CsimpleDll2::CsimpleDll2()
{
	return;
}

int CsimpleDll2::extfun1(int x, int y)
{
	return x + y;
}

SIMPLEDLL2_API int extFun2(int x, int y, int z)
{
	interior a;
	int b = a.intFun(x, y);
	return b + z;
}

说明的是,在simpleDll2.cpp中定义了个可输出的函数extFun2,用来调用不可输出的类的函数interior::intFun,其定义如下:

int interior::intFun(int x, int y)
{
	return x + y;
}

实际上,可以定义extFun2只实现intFun的功能,视实际需要而定。

写完这个简单示例,就可以编译了。build完之后,会发现在solution(注意是solution即simpleDll2根目录,而不是simpleDll2工程目录下)的Debug路径下,出现了simpleDll2.lib,simpleDll2.dll。

2.2、创建测试工程

在开发阶段,可以在工程里新建一个测试工程,用于测试链接库的功能和调试。

右键点击工程,选择add,new project,选择win32 console application工程,取名testdll。建好后是这样的:

注意!需要配置环境!因为和simpledll2工程在一个solution下,所以vs自动创建的结构,一般配置是这样的:

右键单击testdll工程,打开propoties,在VC++ Directories选项页面里,include Directories设置在最前面加上:..\simpleDll2; Library Directories设置在最前面加上:..\Debug; 在Linker --->  input 选项页Additional Dependencies设置在最前面加上:simpleDll2.lib; 

在testdll.cpp添加:

// testdll.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include "simpleDll2.h"
#include <iostream>

int _tmain(int argc, _TCHAR* argv[])
{
	int a = 0;
	CsimpleDll2 cs;
	a = cs.extfun1(3, 4);
	std::cout << "a:" << a << std::endl;

	int b = extFun2(1, 2, 3);
	std::cout << "b:" << b << std::endl;

	//int c = intFun(1, 2); ERROR!!
	return 0;
}

测试的结果为:

a:7
b:6

2.3、封装好的库被外部测试

假设我们已经开发完成交付用户。用户可以拿着你的库进行二次开发。现在模拟用户,看如何二次开发,或者说我们可以测试下是否可以用我们自己的库二次开发。

首先,搭好结构:我起了一个文件夹叫“dev”,里面有:

一个一个梳理:

(1)3rdparty文件夹是二次开发用到所有的第三方库相关的.h和lib文件都放在这里。注意我们刚才写的simpleDll2这里已经成为第三方库了。因为开发一个软件需要用到很多第三方库,所以建立这样一个文件夹进行统一管理是非常必要的。3rdparty文件夹里面的结构如下:

include里面放置simpleDll2.h,这个文件夹里放置所有头文件,这样在工程设置时只用设置这一个路径就行了。

simpleDll2里面放置的是simpleDll2.lib。不同的库就起个文件夹放置,或者也可以统一管理。我这里是单独放置的。

(2)回到上次目录dev文件夹下,进入bin_Debug文件夹,将simpleDll2.dll放置进去。注意一会测试的工程要改生成路径!

这个bin_Debug文件放置了执行程序(debug版本,release起名叫bin)和所需要的动态链接库,也就是刚才放置进去的dll们。

(3)proj就是新建的二次开发工程,里面内容如下:

源码在其自己的proj子文件夹下。

打开proj工程,右键单击工程名称,配置环境:

打开propoties,注意:在General选项页中的Output directories里面,删掉原来的内容,改为:..\..\bin_Debug

其它设置根据工程文件夹的结构,在VC++ Directories选项页面里,include Directories设置在最前面加上:..\..\3rdparty\include; Library Directories设置在最前面加上:..\..\3rdparty\simpleDll2; 在Linker --->  input 选项页Additional Dependencies设置在最前面加上:simpleDll2.lib; 

完成配置。注意..\表示上一级,这个以proj.vcxproj位置为准。因为要往上两级才到dev根目录,所以要两个..\

在proj.cpp中的main函数中添加刚才同样的测试代码,可以得到测试结果。

(4)上面三个文件实际上就够用了,根本不需要simpleDll2.cpp. 但是因为有的时候用户或者有的要求要的,可以建立一个src文件夹,将这个cpp文件放进去,供二次开发参考,实际上里面也没有什么有营养的东西。。。因为主要的备注都会写在头文件里了。

3、Qt创建工程

猜你喜欢

转载自blog.csdn.net/foreverhehe716/article/details/82183220