C/C++封装:Windows/Linux下封装.lib/.so文件

简介: 这里提供了两个C/C++中服务器与客户端之间通讯的两个程序,程序中封装了通信之间的函数方法,我们以这个程序为例进行封装。

C/C++ TCP/IP通信函数


这里提供了两个C/C++中服务器与客户端之间通讯的两个程序,程序中封装了通信之间的函数方法,我们以这个程序为例进行封装。

文件目录结构按照C/C++标准开源项目进行存放:


├─bin
├─doc
├─lib
└─src
    ├─xsocket
    │  │  XTCP.h
    │  │  XTCP.cpp


XTCP.h


#ifndef XTCP_H //保证只初始化一次
#define XTCP_H
#ifdef WIN32
#pragma once
#ifdef XSOCKET_EXPORTS
#define XSOCKET_API __declspec(dllexport)
#else
#define XSOCKET_API __declspec(dllimport)
#endif
#else
#define XSOCKET_API
#endif // WIN32
#include<string>
class XSOCKET_API XTCP
{
public:
  int createSocket();
  bool bindListen(unsigned short port);
  void closeSocket();
  int receiveData(char* buf,int bufsize);
  int sendData(const char* buf, int sendsize);
  bool connectSocket(const char* ip, unsigned short port);
  XTCP acceptClient();
  XTCP();
  virtual ~XTCP();
  int sock = 0;
  unsigned short port = 0;
  char ip[16];
};
#endif // !XTCP_H


XTCP.cpp


#include "XTCP.h"
#ifdef WIN32
#include<Windows.h>
#define socklen_t int
#else
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<arpa/inet.h>
//函数名替换,重定义,将close关闭sock的函数转化为closesocket
#define closesocket close
#define strcpy_s strcpy
#endif
#include <iostream>
#include<stdlib.h>
#include<cstring>
XTCP::XTCP() {
#ifdef WIN32
  static bool is_first = true;
  if (is_first) {
    is_first = false;   
    //通过进程启动Winsock DLL使用
    WSADATA ws;
    WSAStartup(MAKEWORD(2, 2), &ws);    
  }
#endif
}
bool XTCP::connectSocket(const char* ip, unsigned short port) {
  if (sock <= 0) {
    createSocket();
  }
  sockaddr_in saddr;
  saddr.sin_family = AF_INET;
  saddr.sin_port = htons(port);
  //将字符串ip地址转化为网络地址
  saddr.sin_addr.s_addr = inet_addr(ip);
  if (connect(sock, (const sockaddr*)&saddr, sizeof(saddr)) != 0) {
    // strerror(errno)将错误转化为字符串
    std::cout << "connect " << ip << " : " << port << " failed! ";
    return false;
  }
  std::cout << "connect " << ip << " : " << port << " success!\n ";
  return true;
}
int XTCP::createSocket() {
  //创建socket,创建失败返回-1,AF_INET表示ipv4协议,SOCK_STREAM表示接受tcp/ip协议的数据
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock == -1) {
    std::cout << "create socket failed" << std::endl;
  }
  return sock;
}
bool XTCP::bindListen(unsigned short port) {
  if (sock <= 0) {
    createSocket();
  }
  //绑定地址
  sockaddr_in saddr;
  saddr.sin_family = AF_INET;
  //大端字节序和小端字节序的问题,
  saddr.sin_port = htons(port);
  //0设置为绑定本机地址
  saddr.sin_addr.s_addr = htonl(0);
  //绑定地址
  if (bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0) {
    std::cout << "bind port " << port << " failed.\n";
    return false;
  }
  std::cout << "bind port " << port << " successful.\n";
  //监听客户端发送的信息
  //backlog=10表示缓冲大小
  listen(sock, 10);
  return true;
}
XTCP XTCP::acceptClient() {
  XTCP tcp;
  //每个连接就会生成一个client
  sockaddr_in caddr;
  socklen_t len = sizeof(caddr);
  //在accept之前会进行三次握手(由操作系统完成),accept只是获取了握手后的信息
  int client_sock = accept(sock, (sockaddr*)&caddr, &len);
  if (client_sock <= 0) {
    return tcp;
  }
  tcp.sock = client_sock;
  std::cout << "accept client " << client_sock << ".\n";
  char* ip = inet_ntoa(caddr.sin_addr);
  strcpy_s(tcp.ip, ip);
  tcp.port = ntohs(caddr.sin_port);
  std::cout << "client ip address " << tcp.ip << ".\n";
  std::cout << "client port " << tcp.port << ".\n";
  return tcp;
}
int XTCP::receiveData(char* buf, int bufsize) {
  return recv(sock, buf, bufsize, 0);
}
int XTCP::sendData(const char* buf, int sendsize) {
  //需要全部发送完全才能结束
  int sendedSize = 0;
  while (sendedSize!=sendsize) {
    int len = send(sock, buf + sendedSize, sendsize - sendedSize, 0);
    if (len <= 0) {
      break;
    }
    sendedSize += len;
  }
  return sendedSize;
}
void XTCP::closeSocket() {
  if (sock <= 0) {
    return;
  }
  closesocket(sock);
}
XTCP::~XTCP() {
}


Linux封装.so文件


首先编写编写makefile文件,用于编译两个程序,可以按照以下命令进行编译,编译后将会在同级目录下生成一个libxsokcet.so文件,理论上这个时候Linux封装就完成了。


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


但是在实际过程中,常常会出现一个.so文件不存在/找不到的问题。我们在这里编写一个测试程序,项目创建在和xsocket的同级目录,测试libxsocket.so是否可以调用。


testTCP.cpp


#include <iostream>
#include"XTCP.h"
int main()
{
  XTCP client;
  client.connectSocket("192.168.245.129", 8080);
  return 0;
}


我们通过以下程序编译这个程序之后:


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


可以发现,尽管我们在编译过程中设置了libxsocket.so的路径所在位置,但是在运行之后还是会存在找不到文件,报错内容如下error while loading shared libraries: libxsocket.so: cannot open shared object file: No such file or directory,所以在运行的时候需要重新编写一个脚本,来执行testTCP,并且显示指定libxsocket.so的路径所在位置,脚本如下所示:


export LD_LIBRARY_PATH=../xsocket
./testTCP


这样testTCP就执行成功了。


Windows封装.lib文件


Windows封装.lib文件,我们借助vs studio 2019编译器完成编译,还是以上述两个文件和文件结构为例:


首先在xsocket的同级目录创建一个项目(选择具有导出项的(DLL)动态链接库,千万不要选错了),项目名自取。


3f99f78582be4f16b91437189dad8d0e.png


项目创建后将会自动生成一些配置文件,如下图所示


d1d7370fff5a4de8a8571b675675446b.png


然后将XTCP.h和XTCP.cpp文件添加到目前这个新建的项目中来,文件结构如上图所示,具体简体方法,


1.XTCP.h和XTCP.cpp文件添加到当前项目目录。

2.选择 头文件 -> 添加 -> 现有项 ,添加XTCP.h文件。

3.XTCP.cpp文件和XTCP.h文件添加方法一致。


d3a0b238a932451da2fcfd01fa0123fa.png


添加文件后,需要设定一系列的项目配置项:


1、选择项目,右键,选择属性


2b7e377da0cb4826ae975fcc86954581.png


修改输出目录


6c7cc2ad1945436484df716e75360430.png


修改工作目录


de7399296fbb44c998443c0a562f230f.png


取消预编译头


cf33385f85ea4aa0b89a2878ddcd5abc.png


修改导出库目录


b6b39cff132c4b218abd0611bfd067df.png


然后点击运行就会在bin目录生成和项目同名的dll文件了。


中间可能会有一个弹窗显示错误,可以忽略,只要编译显示没有失败/错误就行。


ca4633b7b62d4381aa88403c3211d3c0.png


验证是否可以使用,在项目目录新建一个项目,用于验证该dll是否可以使用:


在新建项目的 解决方案上右键,选择添加现有项目,将刚才打包的项目添加进行,选择.vcxproj文件。


b9aa2cc55426405083650f7ca10d5384.png

a49540b2da2d4afda00604c8b28a07a6.png


然后再右键 解决方案 ,设置启动项目和项目依赖项,


481915c8ae8c45998c090ff43115ec38.png


按照下图设置,设置新建项目为主项目,依赖项目为打包项目。


913ca72ae6384ab2b8ffaa60283b99a2.png

a9262fc0a9f849f29b74b83f2fc2bebd.png


然后再设置当前项目的动态链接库位置,选择当前项目,右键,选择属性,如下图所示:


7703307330d949ada2b9795f1495ff9b.png

49d1ea1edbd24636bb8514048c19fdfe.png

b9ab9236946a4166af1c9330fd10ee23.png

ab02fb0c3efd405882306a099b111707.png

87cb84d8200b4f60a3c51cb4810775e4.png

16c2eedf031a49da887a84adb5fdb328.png


然后再在当前项目新建一个cpp文件运行以下程序,


#include <iostream>
#include"XTCP.h"
int main()
{
  XTCP client;
  client.connectSocket("192.168.245.129", 8080);
  return 0;
}


如果不报错则,动态链接库封装成功。

相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
目录
相关文章
|
7天前
|
C++ 内存技术
[转]Visual C++内嵌swf文件并播放
[转]Visual C++内嵌swf文件并播放
|
6天前
|
Linux API C++
超级好用的C++实用库之文件目录操作
超级好用的C++实用库之文件目录操作
14 0
|
1月前
|
数据安全/隐私保护 C语言 C++
C++(七)封装
本文档详细介绍了C++封装的概念及其应用。封装通过权限控制对外提供接口并隐藏内部数据,增强代码的安全性和可维护性。文档首先解释了`class`中的权限修饰符(`public`、`private`、`protected`)的作用,并通过示例展示了如何使用封装实现栈结构。接着介绍了构造器和析构器的使用方法,包括初始化列表的引入以及它们在内存管理和对象生命周期中的重要性。最后,通过分文件编程的方式展示了如何将类定义和实现分离,提高代码的模块化和复用性。
|
2月前
|
Unix Linux Ruby
在windows和linux上高效快捷地发布Dash应用
在windows和linux上高效快捷地发布Dash应用
|
2月前
|
Ubuntu Linux 虚拟化
安装Windows Linux 子系统的方法:适用于windows 11 版本
本文提供了在Windows 11系统上安装Linux子系统(WSL)的详细步骤,包括启用子系统和虚拟化功能、从Microsoft Store安装Linux发行版、设置WSL默认版本、安装WSL2补丁,以及完成Ubuntu的首次安装设置。
130 2
|
22天前
|
JavaScript 前端开发 测试技术
一个google Test文件C++语言案例
这篇文章我们来介绍一下真正的C++语言如何用GTest来实现单元测试。
14 0
|
25天前
|
Linux 开发者 Python
从Windows到Linux,Python系统调用如何让代码飞翔🚀
【9月更文挑战第10天】在编程领域,跨越不同操作系统的障碍是常见挑战。Python凭借其“编写一次,到处运行”的理念,显著简化了这一过程。通过os、subprocess、shutil等标准库模块,Python提供了统一的接口,自动处理底层差异,使代码在Windows和Linux上无缝运行。例如,`open`函数在不同系统中以相同方式操作文件,而`subprocess`模块则能一致地执行系统命令。此外,第三方库如psutil进一步增强了跨平台能力,使开发者能够轻松编写高效且易维护的代码。借助Python的强大系统调用功能,跨平台编程变得简单高效。
18 0
|
1月前
|
Linux 网络虚拟化 Windows
ccproxy windows上用的代理软件(类似linux系统上的squid)
ccproxy windows上用的代理软件(类似linux系统上的squid)
|
2月前
|
Linux Windows Python
最新 Windows\Linux 后台运行程序注解
本文介绍了在Windows和Linux系统后台运行程序的方法,包括Linux系统中使用nohup命令和ps命令查看进程,以及Windows系统中通过编写bat文件和使用PowerShell启动隐藏窗口的程序,确保即使退出命令行界面程序也继续在后台运行。
|
5月前
|
Oracle Java 关系型数据库
windows 下 win11 JDK17安装与环境变量的配置(配置简单详细,包含IJ中java文件如何使用命令运行)
本文介绍了Windows 11中安装JDK 17的步骤,包括从官方网站下载JDK、配置环境变量以及验证安装是否成功。首先,下载JDK 17的安装文件,如果没有Oracle账户,可以直接解压缩文件到指定目录。接着,配置系统环境变量,新建`JAVA_HOME`变量指向JDK安装路径,并在`Path`变量中添加。然后,通过命令行(cmd)验证安装,分别输入`java -version`和`javac -version`检查版本信息。最后,作者分享了如何在任意位置运行Java代码,包括在IntelliJ IDEA(IJ)中创建的Java文件,只需去掉包声明,就可以通过命令行直接运行。
1637 1
下一篇
无影云桌面