LibTorch C++封装库供C程序调用时链接失败求助
问题:LibTorch C++库导出C接口时链接失败
尝试制作一个LibTorch C++库,通过extern "C"导出函数供C程序调用。库的编译与链接看似正常,但主可执行文件无法完成链接。已将libtorch/lib下所有文件复制到/lib/目录,编译器报出大量LibTorch函数的未定义引用错误。
最小复现代码
Makefile
CFLAGS = -fPIC -Wall -Wshadow -O3 -pthread -I./ CFLAGS2 = -fPIC -Wall -O3 -pthread -I./ LDLIBS = -lm all: libnet test libnet: g++ -shared -o ./libnet.so ./libnet.cpp $(CFLAGS2) \ -I../../libtorch/include/ \ -I../../libtorch/include/torch/csrc/api/include -L/lib \ $(LDLIBS) -ltorch test: gcc -o ./test.exe ./test.c $(CFLAGS) $(LDLIBS) -ltorch ./libnet.so
C主程序 test.c
#include <libnet.h> int main() { void* lstm = create_lstm(2, 64, 256, 1, 60); }
C头文件 libnet.h
void* create_lstm(int layers, int hidden, int nbinputs, int outputs, int batchsize);
库文件 libnet.cpp
#include <torch/torch.h> using namespace torch; struct LSTM_Model : torch::nn::Module { torch::nn::LSTM lstm{ nullptr }; torch::nn::Linear linear{ nullptr }; torch::optim::Adam* opt{ nullptr }; uint64_t _batchsize; uint64_t _hidden; LSTM_Model(uint64_t layers, uint64_t hidden, uint64_t inputs, uint64_t outputs, uint64_t batchsize) { lstm = register_module("lstm", torch::nn::LSTM( torch::nn::LSTMOptions(inputs, hidden) .num_layers(layers))); linear = register_module("linear", torch::nn::Linear( hidden, outputs)); _batchsize = batchsize; _hidden = hidden; } torch::Tensor forward(torch::Tensor x) { auto lstm1 = lstm->forward(x.view({ x.size(0), _batchsize, -1 })); auto out = linear->forward( std::get<0>(lstm1) .view({ _batchsize, x.size(0), _hidden })); return out; } }; extern "C" void* create_lstm(int layers, int hidden, int nbinputs, int outputs, int batchsize) { LSTM_Model* model = new LSTM_Model(layers, hidden, nbinputs, outputs, batchsize); model->opt = new torch::optim::Adam(model->parameters(), torch::optim::AdamOptions(2e-4). betas(std::make_tuple(0.5, 0.5))); return (void*)model; }
链接错误信息(中文翻译)
/usr/bin/ld : ./libnet.so : 未定义的引用 « vtable for torch::optim::Optimizer » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::to(c10::Device, c10::ScalarType, bool) » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::LSTMOptions::LSTMOptions(long, long) » /usr/bin/ld : ./libnet.so : 未定义的引用 « c10::detail::torchInternalAssertFail(char const*, char const*, unsigned int, char const*, char const*) » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::LSTMImpl::LSTMImpl(torch::nn::LSTMOptions const&) » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::train(bool) » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::LinearOptions::LinearOptions(long, long) » /usr/bin/ld : ./libnet.so : 未定义的引用 « typeinfo for torch::nn::Module » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::is_serializable() const » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::pretty_print(std::ostream&) const » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::zero_grad(bool) » /usr/bin/ld : ./libnet.so : 未定义的引用 « vtable for torch::nn::Module » /usr/bin/ld : ./libnet.so : 未定义的引用 « vtable for torch::optim::AdamOptions » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::optim::OptimizerParamGroup::options() const » /usr/bin/ld : ./libnet.so : 未定义的引用 « typeinfo for torch::nn::LinearImpl » /usr/bin/ld : ./libnet.so : 未定义的引用 « c10::detail::torchCheckFail(char const*, char const*, unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::optim::AdamOptions::AdamOptions(double) » /usr/bin/ld : ./libnet.so : 未定义的引用 « c10::UndefinedTensorImpl::_singleton » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::LinearImpl::LinearImpl(torch::nn::LinearOptions const&) » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::clone(std::optional<c10::Device> const&) const » /usr/bin/ld : ./libnet.so : 未定义的引用 « vtable for torch::optim::Adam » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::to(c10::ScalarType, bool) » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::parameters(bool) const » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::optim::OptimizerParamGroup::has_options() const » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::is_training() const » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::to(c10::Device, bool) » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::optim::OptimizerParamGroup::params() const » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::optim::Optimizer::add_param_group(torch::optim::OptimizerParamGroup const&) » /usr/bin/ld : ./libnet.so : 未定义的引用 « c10::detail::torchCheckFail(char const*, char const*, unsigned int, char const*) » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::load(torch::serialize::InputArchive&) » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::save(torch::serialize::OutputArchive&) const » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::Module() » /usr/bin/ld : ./libnet.so : 未定义的引用 « torch::nn::Module::clone_(torch::nn::Module&, std::optional<c10::Device> const&) » collect2: error: ld returned 1 exit status make: *** [Makefile:14 : test] 错误 1
解决方法
1. 链接完整的LibTorch依赖库
仅链接-ltorch不足以覆盖所有依赖,需要添加-ltorch_cpu、-lc10等核心库。推荐使用LibTorch自带的torch-config工具自动获取正确的编译和链接参数:
g++ -shared -o ./libnet.so ./libnet.cpp $(CFLAGS2) \ -I../../libtorch/include/ \ -I../../libtorch/include/torch/csrc/api/include \ -L../../libtorch/lib \ $(LDLIBS) `../../libtorch/bin/torch-config --cxxflags --libs`
2. 编译共享库时指定动态库路径
添加-Wl,-rpath,../../libtorch/lib参数,让链接器记录LibTorch库的路径,避免运行时和链接时找不到依赖:
g++ -shared -o ./libnet.so ./libnet.cpp $(CFLAGS2) \ -I../../libtorch/include/ \ -I../../libtorch/include/torch/csrc/api/include \ -L../../libtorch/lib \ -Wl,-rpath,../../libtorch/lib \ $(LDLIBS) -ltorch -ltorch_cpu -lc10
3. 用g++编译C主程序
虽然主程序是C代码,但libnet.so是C编译的,链接时需要C标准库支持,因此用g++替代gcc编译test.exe:
g++ -o ./test.exe ./test.c $(CFLAGS) $(LDLIBS) -L../../libtorch/lib -Wl,-rpath,../../libtorch/lib -ltorch ./libnet.so
4. 避免手动复制LibTorch库到系统目录
直接使用LibTorch自带的lib路径更可靠,复制到/lib可能引发版本不匹配或权限问题。
内容的提问来源于stack exchange,提问作者Bertrand125
相关产品推荐
相关产品推荐

