将一个类封装到dll和linux的so


这篇博客里封装了一个tcp网络类,每次开发我门只需要加载这个动

态库,这个模块.就可以使用里面的函数.使用动态库的好处就是

编译速度很快。



  1首先添加到windows的dll动态库里面.

新建一个VS里的win32控制台程序。然后选择动态化

选择导出符合,导出符合的好处就是,有一些宏已经定义好了

wKioL1lpyhjCSOFyAABFEvX8cDo621.png-wh_50

然后添加现有项,把之前封装的XTCO封装进来。


在Windows中,直接这样是不行的,我们要添加宏定义

wKiom1lpy5jhrPkpAADv-g79eck008.png-wh_50


添加到这个类的最顶部,这个定义的意思是:如果定义了

这个宏,我就把XTCP定义成  __declspec(dllexport)

否则的__declspec(dllimport)

当一个新项目调用他的时候,他就是没有定义 那么就是

__declspec(dllimport) 也就是导入的状态。

简单点就是 clsss __declspec(dllexport) XTCP

如果是用户调用的时候 clsss __declspec(dllimport) XTCP


wKioL1lpzLqjGBRKAAAqKDmumdQ908.png-wh_50


这个dll项目在VS里的预处理器是早就预定义好的

当你创建一个新的c++项目是不会有这个定义的

wKioL1lpzRXziyYXAAGv9h4t-pE425.png-wh_50


平台工具集要改成,WIN ..xp否则XP不能用这个dll

wKioL1lp0MrAOmDMAACuTZkN0U8359.png-wh_50


改变生成的lib文件位置

wKioL1lp0VuiiLcXAAAw1lkFcLw522.png-wh_50


工作目录都改成../../bin,

因为你执行调试的时候会在这个目录找生成的文件

虽然他是dll文件。


wKiom1lp0bfzU_1WAAAdxo7G400532.png-wh_50


生成成功是没有任何问题的。

wKioL1lp1HuDDd49AAGTC72fGKk936.png-wh_50


我们测试一下:

创建一个新的项目

wKiom1lp1S_TO4k2AACS1MOUnQE060.png-wh_50


1 包含XTCP.h所在的目录

wKiom1lp1uvRiJ7LAAAt2p0_ej4491.png-wh_50

2 .lib所在的目录  

wKioL1lp2NeycX0rAADZoUZtFJ4053.png-wh_50




3加载lib文件

wKiom1lp12vBn5_rAACtLNT1iO0506.png-wh_50


当他调用这个的时候会把这个lib文件编译到exe执行文件里

通过这个lib加载dll, 调用里边的函数



测试部分------------------------------------


我们直接绑定就好了,因为在Bind函数里直接调用了。

CreateSocket()函数,他会对调用他的对象里的m_sock进行赋值

wKiom1lp2iujVuIKAABMa5S7rk0874.png-wh_50

测试代码如下: 完全没有任何问题

#include "XTCP.h"
#include <thread>
#include <string.h>
class TcpThread
{
public:
//线程入口函数 创建一个
void Main()
{
char buf[1024];
for (;;)
{
memset(buf, 0, sizeof(buf));
int recv_len = client.Recv(buf, sizeof(buf) - 1);
if (recv_len <= 0)break;
if (strstr(buf, "quit") != NULL)
{
char re[] = "quit success\n";
int sendlen = client.Send(re, strlen(re) + 1);
break;
}
char p_ok[] = "ok\n";
int sendlen = client.Send(p_ok, strlen(p_ok));
printf("recv %s\n", buf);
}
client.Close();
delete this;
}
//用户的socket
XTCP client;
};
int main(int argc,char *argv[])
{
unsigned short port = 8081;
XTCP server;
server.Bind(port);
//单线程测试
for (;;)
{
XTCP client = server.Accept();
//创建线程
TcpThread *th = new TcpThread();
th->client = client;
std::thread sthr(&TcpThread::Main, th);
// 释放主线程占用的资源
sthr.detach();
}
server.Close();
getchar();
return 0;
}




     2添加到Linux的so文件中

创建一个makefile在windows进行编辑,使用文本编辑器打开

目标文件libxsocket.so:依赖文件:XTCP.cpp XTCP.h

用g++编译 $+(依赖项) -o $@(表示目标) -fpic(代码与位置无关)

(这样我门调用的时候,只有通过名字就能找到函数的定义,)

-shared(表示把他编程动态库)-std=c++11(动态库用到了c++11)

完整就是这样,输入make命令就会直接编译


注意Linux的文件你必须是lib开头.so结尾。当你在Linux里

用这个库的时候,只需要用中间这个名字就行了


libxsocket.so:XTCP.cpp XTCP.h
g++ $+ -o $@ -fpic -shared -std=c++11

注意的是一些宏定义在linux

可以用 来解决

#ifdef WIN32

#ifdef XSOCKET_EXPORTS

#define XSOCKET_API __declspec(dllexport)

#else

#define XSOCKET_API __declspec(dllimport)

#endif


#else

#define XSOCKET_API

#endif

成功生成

wKioL1lp4e7SGoIDAACMEsjT-l4788.png-wh_50



#include "XTCP.h"
#include <thread>
#include <string.h>
class TcpThread
{
public:
//线程入口函数 创建一个
void Main()
{
char buf[1024];
for (;;)
{
memset(buf, 0, sizeof(buf));
int recv_len = client.Recv(buf, sizeof(buf) - 1);
if (recv_len <= 0)break;
if (strstr(buf, "quit") != NULL)
{
char re[] = "quit success\n";
int sendlen = client.Send(re, strlen(re) + 1);
break;
}
char p_ok[] = "ok\n";
int sendlen = client.Send(p_ok,strlen(p_ok));
printf("recv %s\n", buf);
}
client.Close();
delete this;
}
//用户的socket
XTCP client;
};
int main(int argc,char*argv[])
{
unsigned short port = 8016;
XTCP mytcp;
//创建
mytcp.CreateSocket();
//绑定
if (!mytcp.Bind(port))
return -1;
for (;;)
{
XTCP client = mytcp.Accept();
//创建线程
TcpThread *th = new TcpThread();
th->client = client;
std::thread sthr(&TcpThread::Main, th);
// 释放主线程占用的资源
sthr.detach();
}
mytcp.Close();
getchar();
return 0;
}


用上面测试dll的代码就行,然后用

wKiom1lp5KiBUA7UAAA0A3ccqSs427.png-wh_50


在写一个makefile来编译他,用到linux的so文件

目标文件:依赖文件

tcpserver:server.cpp

g++ $+(依赖项) -o $@(目标项) -I../xsocket(XTCP.h头文件路径)

-std=c++11(c++11) -lpthread(线程库)

-lxsocket(使用libxsocket.so库文件,因为linux这个so文件,前面

必须要lib开头,尾部必须要.so结尾,用的时候只有中间的xsocket就行);

-L../xsocket so所在的路径

但是会有错误 我们写个脚本: vim run

里面填写路径

第一行是 so的路径

第二行是执行的程序

wKiom1lp6BvR9n4kAABClp88XuQ718.png-wh_50

命令:chmod +x run给他执行权限

然后./run执行一下


关于so 找不到的问题后续解决,

qq:2438746951






2017年7月7日补充: Linux  so的封装和测试

首先,有XTCP类:XTCP.h XTCP.cpp文件。

1生成so文件  makefile

libxsocket.so 是目标文件,XTCP.cpp XTCP.h是依赖文件

 g++是编译器,$+ 代表依赖文件,-o代表指定目标名称, 

$@代表目标文件, -fpic -shared是生成so库要加的命令

-std=c++11代表用到了c++11,生成成功后,


libxsocket.so:XTCP.cpp XTCP.h
        g++ $+ -o $@ -fpic -shared -std=c++11



测试程序的生成,测试代码上面以及写了,和dll测试一样的,

但是linux用的是so库。


server:server.cpp
        g++ $+ -o $@ -I../xsocket -std=c++11 -lpthread -lxsocket -L../xsocket


wKiom1lsHCDzcu_FAAA7kqrHTZQ631.png-wh_50