【发布时间】:2022-01-12 12:13:55
【问题描述】:
我对 C++/CMake 还是很陌生,我正在尝试创建一个可以编译 GRPC 项目的 CMake 文件。我可以使用这个 CMake 生成客户端(只需要客户端)文件,但我正在尝试创建另一个文件(base.cpp),它将从其中一个文件中导入一个类(ManagerClient)。我决定为这个我想要的文件创建一个头文件,名为manager_client.h。
我不太确定要在 CMake 文件的哪个位置编译 base.cpp,因此将其添加为目标目录之一,并假设我制作的头文件会自动链接。运行make 后,出现此错误:
Undefined symbols for architecture x86_64:
"ManagerClient::ManagerClient(std::__1::shared_ptr<grpc::Channel>)", referenced from:
ReadUntilClient::ReadUntilClient() in base.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [base] Error 1
make[1]: *** [CMakeFiles/base.dir/all] Error 2
make: *** [all] Error 2
我找到了这个question,但并没有真正解释如何解决我的问题。奇怪的是在制作base.cpp 之前,我能够在manager_client.cpp 的主函数中运行base.cpp 逻辑而没有任何问题,所以我怀疑我是通过CMake 还是我的头文件编译错了是错的。有什么想法吗?
代码如下:
manager_client.cpp
#include <grpcpp/grpcpp.h>
#include <grpc/grpc.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h>
#include <string>
#include <memory>
#include "minknow_api/manager.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using grpc::ClientReader;
using minknow_api::manager::ManagerService;
using minknow_api::manager::FlowCellPositionsRequest;
using minknow_api::manager::FlowCellPositionsResponse;
class ManagerClient {
public:
ManagerClient(std::shared_ptr<Channel> channel) : stub_(ManagerService::NewStub(channel)) {}
std::unique_ptr<ClientReader<FlowCellPositionsResponse> > flow_cell_positions(FlowCellPositionsRequest request) {
ClientContext context;
return stub_->flow_cell_positions(&context, request);
}
private:
std::unique_ptr<ManagerService::Stub> stub_;
};
int main(int argc, char* argv[]) {
return 0;
}
manager_client.h
#pragma once
#include <grpcpp/grpcpp.h>
#include <grpc/grpc.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h>
#include <string>
#include <memory>
#include "minknow_api/manager.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using grpc::ClientReader;
using minknow_api::manager::ManagerService;
using minknow_api::manager::FlowCellPositionsRequest;
using minknow_api::manager::FlowCellPositionsResponse;
class ManagerClient {
public:
ManagerClient(std::shared_ptr<Channel> channel);
std::unique_ptr<ClientReader<FlowCellPositionsResponse> > flow_cell_positions(FlowCellPositionsRequest request);
private:
std::unique_ptr<ManagerService::Stub> stub_;
};
base.cpp
#include <grpcpp/grpcpp.h>
#include <grpc/grpc.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h>
#include <string>
#include <thread>
#include <memory>
#include <iostream>
#include "manager_client.h"
#include "minknow_api/manager.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using grpc::ClientReader;
using minknow_api::manager::FlowCellPositionsRequest;
using minknow_api::manager::FlowCellPositionsResponse;
class ReadUntilClient {
public:
ManagerClient manager;
ReadUntilClient() : manager(grpc::CreateChannel("127.0.0.1:9501",
grpc::InsecureChannelCredentials())) {}
};
int main(int argc, char* argv[]) {
ReadUntilClient client;
return 0;
}
CMakeLists.txt
// Above this I compile the proto files & I only included the code for relevant files
add_library(rg_grpc_proto
${man_grpc_srcs}
${man_grpc_hdrs}
${man_proto_srcs}
${man_proto_hdrs})
target_link_libraries(rg_grpc_proto
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF})
foreach(_target
manager_client
base)
add_executable(${_target}
"${_target}.cpp")
target_link_libraries(${_target}
rg_grpc_proto
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF})
endforeach()
【问题讨论】:
-
你有一个ODR违规,
ManagerClient在manager_client.cpp和manager_client.h中的声明是不同的,manager_client.cpp应该包括manager_client.h而不是声明ManagerClient的新副本,只需定义构造函数和方法