将Eigen::TensorBase作为函数参数使用时遇到问题
Eigen Tensor跨库函数指针问题解决方案
问题1:获取TensorBase底层数据指针和元素总数
Eigen的TensorBase采用CRTP(奇异递归模板模式)设计,需通过derived()方法获取实际的Tensor实例,再调用data()获取数据指针,size()获取总元素数。修正后的process_tensor实现如下:
// 通用数据处理函数 template<typename T> bool process_data(const T* ptr, size_t N) { // 自定义逻辑 return false; } // 修正后的Tensor数据处理接口(适配任意秩) template<typename Derived> bool process_tensor(const Eigen::TensorBase<Derived, Eigen::ReadOnlyAccessors>& tensor) { using ScalarType = typename Derived::Scalar; // 获取底层const数据指针 const ScalarType* data_ptr = tensor.derived().data(); // 获取Tensor总元素数 size_t total_elements = tensor.derived().size(); return process_data(data_ptr, total_elements); }
问题2:函数指针类型不匹配
原代码核心错误是模板参数设计错误:process_tensor的模板参数应为Tensor的派生类型(如Eigen::Tensor<float,3>),而非标量类型float。此外,不同秩的Tensor对应不同的模板实例,无法用单一函数指针适配所有秩的Tensor。
针对跨库函数指针的需求,最可靠的方案是直接暴露process_data的函数指针,由调用方自行从Tensor中提取数据指针和元素数:
// 跨库共享的函数指针(处理float类型数据) bool (*process_data_float_ptr)(const float*, size_t) = process_data<float>; // 测试调用 void test() { Eigen::Tensor<float, 3> tensor(2, 3, 4); // 调用方自行适配Tensor process_data_float_ptr(tensor.data(), tensor.size()); }
若坚持封装Tensor适配逻辑,可定义非模板通用函数,通过void*传递数据(需确保跨库ABI兼容性):
// 封装Tensor适配的非模板函数 bool process_tensor_float(const void* tensor_data, size_t num_elements) { return process_data(static_cast<const float*>(tensor_data), num_elements); } // 跨库函数指针 bool (*process_tensor_float_ptr)(const void*, size_t) = process_tensor_float; // 测试调用 void test() { Eigen::Tensor<float, 3> tensor(2, 3, 4); process_tensor_float_ptr(tensor.data(), tensor.size()); }
注:无法用单一函数指针直接接受任意秩的
TensorBase,因为不同秩的Tensor对应不同的模板实例,函数签名本质不同,C++不支持这种动态类型的函数指针匹配。
内容的提问来源于stack exchange,提问作者ScratchingTheSurface
相关产品推荐
相关产品推荐

