.proto 파일을 이용해 데이터를 정의하고 코드 생성기로 해당 언어의 소스 파일을 자동으로 생성합니다. Protobuf 설치 및 설정
.proto 파일을 만들고 이를 바탕으로 C++ 코드로 변환합니다.Protocol.proto 파일 작성
syntax = "proto3";를 사용해 Protobuf 버전을 지정합니다.코드 생성
protoc.exe를 사용해 .proto 파일을 바탕으로 C++ 코드(헤더와 소스 파일)를 자동 생성합니다. 라이브러리 세팅
데이터 직렬화/역직렬화
SerializeToArray와 ParseFromArray를 사용해 데이터를 직렬화하거나 역직렬화합니다.Protocol.proto 파일은 데이터의 구조를 정의합니다.
syntax = "proto3";
package Protocol;
message BuffData
{
uint64 buffId = 1; // 버프 ID
float remainTime = 2; // 남은 시간
repeated uint64 victims = 3; // 가변 데이터: 희생자 목록
}
message S_TEST
{
uint64 id = 1; // ID
uint32 hp = 2; // 체력
uint32 attack = 3; // 공격력
repeated BuffData buffs = 4; // 버프 리스트 (가변 데이터)
}
uint64, float, uint32 등 기본 데이터 타입을 사용합니다. protoc.exe -I=./ --cpp_out=./ ./Protocol.proto
IF ERRORLEVEL 1 PAUSE
protoc.exe: Protobuf 컴파일러입니다. -I=./: Protocol.proto 파일이 있는 경로를 지정합니다. --cpp_out=./: C++ 소스 코드를 출력할 경로를 지정합니다. Protocol.pb.h: 헤더 파일 Protocol.pb.cc: 소스 파일주의: uint16 타입은 Protobuf에서 지원하지 않으므로, uint32로 대체해야 합니다.
pch.h 수정:
#ifdef _DEBUG
#pragma comment(lib, "Protobuf\\Debug\\libprotobufd.lib")
#else
#pragma comment(lib, "Protobuf\\Release\\libprotobuf.lib")
#endif
이제 Protobuf 라이브러리가 프로젝트에 연결됩니다.
#include "Protocol.pb.h" // 생성된 Protobuf 헤더 파일
while (true)
{
Protocol::S_TEST pkt;
pkt.set_id(1000);
pkt.set_hp(100);
pkt.set_attack(10);
// BuffData 추가
{
Protocol::BuffData* data = pkt.add_buffs();
data->set_buffid(100);
data->set_remaintime(1.2f);
data->add_victims(4000);
}
SendBufferRef sendBuffer = ServerPacketHandler::MakeSendBuffer(pkt);
GSessionManager.Broadcast(sendBuffer);
this_thread::sleep_for(250ms);
}
add_buffs()는 BuffData 객체를 추가합니다. void ClientPacketHandler::Handle_S_TEST(BYTE* buffer, int32 len)
{
Protocol::S_TEST pkt;
// 직렬화된 데이터를 객체로 변환
ASSERT_CRASH(pkt.ParseFromArray(buffer + sizeof(PacketHeader), len - sizeof(PacketHeader)));
cout << pkt.id() << " " << pkt.hp() << " " << pkt.attack() << endl;
cout << "BUFSIZE : " << pkt.buffs_size() << endl;
for (auto& buf : pkt.buffs())
{
cout << "BUFINFO : " << buf.buffid() << " " << buf.remaintime() << endl;
cout << "VICTIMS : " << buf.victims_size() << endl;
for (auto& vic : buf.victims())
cout << vic << " ";
cout << endl;
}
}
protoc-<version>-win64.zip (C++용)protoc.exe (Protobuf 컴파일러)CMake 실행 → 설정:
cmake 폴더 경로를 지정합니다.Configure 버튼 클릭 → Visual Studio 버전 선택.
Generate 버튼 클릭 → 솔루션 파일 생성.
protobuf.sln 파일을 엽니다. ALL_BUILD 프로젝트를 선택 → 빌드 수행.빌드 결과:
protoc.exe: Protobuf 컴파일러 실행 파일libprotobufd.lib (디버그용 라이브러리)libprotobuf.lib (릴리즈용 라이브러리)syntax = "proto3";
package Example;
message SampleMessage {
uint64 id = 1;
string name = 2;
repeated uint32 values = 3;
}
protoc.exe를 사용해 .proto 파일을 C++ 코드로 변환합니다.
protoc --cpp_out=. [대상 proto 파일]
SampleMessage.pb.h 및 SampleMessage.pb.cc 파일이 생성됩니다.라이브러리 디렉터리 설정:
libprotobufd.lib (Debug 모드)libprotobuf.lib (Release 모드)링커 설정:
libprotobufd.lib 또는 libprotobuf.lib 추가.C:\protobuf\srcSampleMessage 생성 및 직렬화:
#include "SampleMessage.pb.h"
#include <iostream>
#include <fstream>
int main() {
Example::SampleMessage msg;
// 데이터 설정
msg.set_id(12345);
msg.set_name("Test Name");
msg.add_values(10);
msg.add_values(20);
// 직렬화
std::ofstream output("output.bin", std::ios::binary);
if (msg.SerializeToOstream(&output)) {
std::cout << "Data serialized successfully!" << std::endl;
}
// 역직렬화
std::ifstream input("output.bin", std::ios::binary);
Example::SampleMessage newMsg;
if (newMsg.ParseFromIstream(&input)) {
std::cout << "ID: " << newMsg.id() << std::endl;
std::cout << "Name: " << newMsg.name() << std::endl;
for (int i = 0; i < newMsg.values_size(); ++i) {
std::cout << "Value: " << newMsg.values(i) << std::endl;
}
}
return 0;
}
| 기능 | 함수 |
|---|---|
| 데이터 설정 | set_<필드이름>(값) |
| 리스트 데이터 추가 | add_<필드이름>(값) |
| 직렬화 (Serialize) | SerializeToArray, SerializeToOstream |
| 역직렬화 (Deserialize) | ParseFromArray, ParseFromIstream |
| 리스트 크기 반환 | <필드이름>_size() |
| 리스트 데이터 접근 | <필드이름>(인덱스) |
런타임 라이브러리 미스매치:
C/C++ → 코드 생성 → 런타임 라이브러리를 일치시킵니다.DLL 파일 누락:
libprotobufd.dll 또는 libprotobuf.dll 파일을 실행 파일과 같은 디렉터리에 배치합니다.