first commit
This commit is contained in:
64
CMakeLists.txt
Normal file
64
CMakeLists.txt
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
project(xrabbitmqclient CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
|
||||||
|
find_package(Boost REQUIRED)
|
||||||
|
find_package(simpleamqpclient CONFIG REQUIRED)
|
||||||
|
|
||||||
|
# 使用 generate_export_header(${PROJECT_NAME}) 时:
|
||||||
|
# - CMake 会自动生成一个头文件,其中包含导出宏
|
||||||
|
# - 宏名称是 项目名称的大写形式 + _EXPORT 后缀
|
||||||
|
include(GenerateExportHeader)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
# 2. 编译封装层为独立库
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
add_library(${PROJECT_NAME}
|
||||||
|
include/RabbitMQClient.h
|
||||||
|
src/RabbitMQClient.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
generate_export_header(${PROJECT_NAME}
|
||||||
|
EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/include/XRabbitMQClient_export.h
|
||||||
|
)
|
||||||
|
|
||||||
|
# 🌟 新增修复:强制 MSVC 使用 UTF-8 编码编译,彻底消灭 C4819 和乱码导致的玄学报错
|
||||||
|
if(MSVC)
|
||||||
|
target_compile_options(${PROJECT_NAME} PRIVATE /utf-8)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# 设置头文件搜索路径
|
||||||
|
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||||
|
$<INSTALL_INTERFACE:include>
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>
|
||||||
|
)
|
||||||
|
# 🌟 修复项:隐藏底层依赖,使用 Conan 声明的准确目标名(小写)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE simpleamqpclient::simpleamqpclient boost::boost)
|
||||||
|
|
||||||
|
# 添加导出宏
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE XRABBITMQCLIENT_LIBRARY)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
# 3. 安装规则 (供 Conan 打包提取使用)
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
# 安装生成的库文件
|
||||||
|
install(TARGETS ${PROJECT_NAME}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # Windows 下的 .dll
|
||||||
|
)
|
||||||
|
|
||||||
|
# 安装暴露给业务层的头文件 (注意:千万不要把 RabbitMQClient.cpp 安装出去)
|
||||||
|
install(FILES
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/IMessageQueue.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/RabbitMQClient.h
|
||||||
|
${CMAKE_BINARY_DIR}/include/XRabbitMQClient_export.h
|
||||||
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
)
|
||||||
91
README_PACKAGE.md
Normal file
91
README_PACKAGE.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# XRabbitMQClient 独立包发布指南
|
||||||
|
|
||||||
|
## 1. 本地构建和测试包
|
||||||
|
|
||||||
|
### 在 XRabbitMQClient 目录下执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd XRabbitMQClient
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
conan install . --build=missing -s build_type=Release -s compiler.cppstd=17
|
||||||
|
|
||||||
|
# 构建包
|
||||||
|
conan build .
|
||||||
|
|
||||||
|
# 创建本地包(会自动构建并打包)
|
||||||
|
conan create . -s build_type=Release -s compiler.cppstd=17
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. 发布到 Conan 远程仓库
|
||||||
|
|
||||||
|
### 2.1 配置远程仓库(如果还没有)
|
||||||
|
```bash
|
||||||
|
# 查看已配置的远程仓库
|
||||||
|
conan remote list
|
||||||
|
|
||||||
|
# 添加远程仓库(示例)
|
||||||
|
conan remote add my-conan-repo https://your-conan-server.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 上传包
|
||||||
|
```bash
|
||||||
|
# 上传到远程仓库
|
||||||
|
conan upload xrabbitmqclient/1.0.0 --remote=my-conan-repo --all
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. 在其他项目中使用 xrabbitmqclient
|
||||||
|
|
||||||
|
### 3.1 在你的项目 conanfile.py 中添加依赖:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from conan import ConanFile
|
||||||
|
|
||||||
|
class MyProjectConan(ConanFile):
|
||||||
|
name = "myproject"
|
||||||
|
version = "1.0.0"
|
||||||
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
|
|
||||||
|
def requirements(self):
|
||||||
|
self.requires("xrabbitmqclient/1.0.0")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 在 CMakeLists.txt 中使用:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
find_package(xrabbitmqclient CONFIG REQUIRED)
|
||||||
|
target_link_libraries(your_target PRIVATE xrabbitmqclient::xrabbitmqclient)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 代码中使用:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <RabbitMQClient.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// 使用 XRabbitMQClient
|
||||||
|
auto client = std::make_unique<RabbitMQClient>();
|
||||||
|
// ...
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 项目结构说明
|
||||||
|
|
||||||
|
```
|
||||||
|
XRabbitMQClient/
|
||||||
|
├── conanfile.py # 独立包的 Conan 配置
|
||||||
|
├── CMakeLists.txt # CMake 构建配置
|
||||||
|
├── include/ # 公开头文件
|
||||||
|
│ ├── IMessageQueue.h
|
||||||
|
│ └── RabbitMQClient.h
|
||||||
|
└── src/ # 源代码
|
||||||
|
└── RabbitMQClient.cpp
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. 版本更新流程
|
||||||
|
|
||||||
|
1. 修改 `conanfile.py` 中的 `version` 字段
|
||||||
|
2. 提交代码变更
|
||||||
|
3. 运行 `conan create .` 创建新版本
|
||||||
|
4. 上传新版本到远程仓库
|
||||||
50
conanfile.py
Normal file
50
conanfile.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
from conan import ConanFile
|
||||||
|
from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout
|
||||||
|
|
||||||
|
class XRabbitMQClientConan(ConanFile):
|
||||||
|
name = "xrabbitmqclient"
|
||||||
|
version = "1.0.0"
|
||||||
|
description = "A C++ wrapper for RabbitMQ based on Interface and Pimpl."
|
||||||
|
license = "MIT"
|
||||||
|
author = "XDL"
|
||||||
|
topics = ("rabbitmq", "amqp", "message-queue")
|
||||||
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
|
|
||||||
|
options = {"shared": [True, False], "fPIC": [True, False]}
|
||||||
|
default_options = {"shared": False, "fPIC": True}
|
||||||
|
|
||||||
|
exports_sources = "CMakeLists.txt", "src/*", "include/*"
|
||||||
|
|
||||||
|
def config_options(self):
|
||||||
|
if self.settings.os == "Windows":
|
||||||
|
del self.options.fPIC
|
||||||
|
|
||||||
|
def configure(self):
|
||||||
|
if self.options.shared:
|
||||||
|
self.options.rm_safe("fPIC")
|
||||||
|
|
||||||
|
def layout(self):
|
||||||
|
cmake_layout(self)
|
||||||
|
|
||||||
|
def requirements(self):
|
||||||
|
self.requires("simpleamqpclient/2.5.1", transitive_headers=True, transitive_libs=True)
|
||||||
|
self.requires("boost/1.78.0")
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
tc = CMakeToolchain(self)
|
||||||
|
tc.generate()
|
||||||
|
deps = CMakeDeps(self)
|
||||||
|
deps.generate()
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
cmake = CMake(self)
|
||||||
|
cmake.configure()
|
||||||
|
cmake.build()
|
||||||
|
|
||||||
|
def package(self):
|
||||||
|
cmake = CMake(self)
|
||||||
|
cmake.install()
|
||||||
|
|
||||||
|
def package_info(self):
|
||||||
|
self.cpp_info.libs = ["xrabbitmqclient"]
|
||||||
|
self.cpp_info.requires = ["simpleamqpclient::simpleamqpclient", "boost::boost"]
|
||||||
19
include/IMessageQueue.h
Normal file
19
include/IMessageQueue.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include "XRabbitMQClient_export.h"
|
||||||
|
|
||||||
|
// 纯虚接口:隔离具体的消息队列实现
|
||||||
|
class XRABBITMQCLIENT_EXPORT IMessageQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IMessageQueue() = default;
|
||||||
|
|
||||||
|
// 连接到消息队列服务器
|
||||||
|
virtual bool Connect() = 0;
|
||||||
|
|
||||||
|
// 发送消息
|
||||||
|
virtual bool Publish(const std::string &routing_key, const std::string &message) = 0;
|
||||||
|
|
||||||
|
// 接收消息 (简单阻塞式示例)
|
||||||
|
virtual std::string Consume(const std::string &queue_name) = 0;
|
||||||
|
};
|
||||||
25
include/RabbitMQClient.h
Normal file
25
include/RabbitMQClient.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "IMessageQueue.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class XRABBITMQCLIENT_EXPORT RabbitMQClient : public IMessageQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 传入必要的连接参数
|
||||||
|
RabbitMQClient(const std::string &host, int port, const std::string &username, const std::string &password);
|
||||||
|
|
||||||
|
// 注意:使用 unique_ptr 配合 Pimpl 时,析构函数必须在 .cpp 中实现
|
||||||
|
~RabbitMQClient() override;
|
||||||
|
|
||||||
|
// 实现接口方法
|
||||||
|
bool Connect() override;
|
||||||
|
bool Publish(const std::string &routing_key, const std::string &message) override;
|
||||||
|
std::string Consume(const std::string &queue_name) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Pimpl 核心:前向声明具体的实现类
|
||||||
|
struct Impl;
|
||||||
|
// 使用 unique_ptr 管理实现类的生命周期
|
||||||
|
std::unique_ptr<Impl> pimpl_;
|
||||||
|
};
|
||||||
87
src/RabbitMQClient.cpp
Normal file
87
src/RabbitMQClient.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#include "RabbitMQClient.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// 在这里引入第三方库的头文件!
|
||||||
|
// 这样使用该封装类的业务代码就不会被污染
|
||||||
|
#include <SimpleAmqpClient/SimpleAmqpClient.h>
|
||||||
|
|
||||||
|
// 定义内部实现结构体
|
||||||
|
struct RabbitMQClient::Impl
|
||||||
|
{
|
||||||
|
std::string host;
|
||||||
|
int port;
|
||||||
|
std::string username;
|
||||||
|
std::string password;
|
||||||
|
|
||||||
|
AmqpClient::Channel::ptr_t channel;
|
||||||
|
|
||||||
|
Impl(std::string h, int p, std::string u, std::string pwd)
|
||||||
|
: host(std::move(h)), port(p), username(std::move(u)), password(std::move(pwd)), channel(nullptr) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 构造函数:初始化 pimpl_
|
||||||
|
RabbitMQClient::RabbitMQClient(const std::string &host, int port, const std::string &username, const std::string &password)
|
||||||
|
: pimpl_(std::make_unique<Impl>(host, port, username, password))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// 析构函数:必须在这里定义,此时 Impl 是完整类型,unique_ptr 才能正确释放它
|
||||||
|
RabbitMQClient::~RabbitMQClient() = default;
|
||||||
|
|
||||||
|
bool RabbitMQClient::Connect()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 创建连接
|
||||||
|
pimpl_->channel = AmqpClient::Channel::Create(
|
||||||
|
pimpl_->host, pimpl_->port, pimpl_->username, pimpl_->password);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "RabbitMQ Connection Failed: " << e.what() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RabbitMQClient::Publish(const std::string &routing_key, const std::string &message)
|
||||||
|
{
|
||||||
|
if (!pimpl_->channel)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 确保队列存在 (实际项目中可能在初始化时统一声明)
|
||||||
|
pimpl_->channel->DeclareQueue(routing_key, false, true, false, false);
|
||||||
|
|
||||||
|
AmqpClient::BasicMessage::ptr_t msg = AmqpClient::BasicMessage::Create(message);
|
||||||
|
pimpl_->channel->BasicPublish("", routing_key, msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "Publish Failed: " << e.what() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RabbitMQClient::Consume(const std::string &queue_name)
|
||||||
|
{
|
||||||
|
if (!pimpl_->channel)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pimpl_->channel->DeclareQueue(queue_name, false, true, false, false);
|
||||||
|
std::string consumer_tag = pimpl_->channel->BasicConsume(queue_name, "");
|
||||||
|
|
||||||
|
// 阻塞等待消息
|
||||||
|
AmqpClient::Envelope::ptr_t envelope = pimpl_->channel->BasicConsumeMessage(consumer_tag);
|
||||||
|
return envelope->Message()->Body();
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "Consume Failed: " << e.what() << std::endl;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user