VBA按引用传二维数组给C++ DLL实现[r][c]访问的方案咨询
解决方案
编译期维度固定实现
如果数组行列数是编译期可确定的常量,直接对一维指针做类型强转即可满足需求,修改后可运行代码如下:
// Main.cpp #include <iostream> using namespace std; const int r = 5; const int c = 6; int main() { // 模拟VBA传入的列主序数组 double arr[c][r]={ 1 }; double* arrpt = &arr[0][0]; int i, j, num; num = 0; for (i = 0; i < r; i++ ) { for (j = 0; j < c; j++) { *(arrpt + i +j*r) = (double)num; num++; } } double arr1[r * c]; double* arr1pt = &arr1[0]; for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { *(arr1pt + i*c +j) = *(arrpt + i + j * r); } } // 核心转换逻辑:将一维指针强转为指向[c]个double的数组指针 double (*arr1v)[c] = reinterpret_cast<double(*)[c]>(arr1pt); // 两种访问方式都可正常使用 cout << arr1v[2][3] << endl; // 二维访问形式 cout << arr1pt[2*c + 3] << endl; // 一维访问形式,输出结果与上一行一致 return 0; }
原理:C++原生二维数组的arr[i][j]访问本质就是自动计算*(首地址 + i*列数 + j),将一维指针强转为元素类型 (*)[列数]类型后,编译器会自动完成偏移计算,和手动计算索引的结果完全一致,无额外性能损耗。
运行期动态维度实现
实际从VBA传入的行列数多为动态值,编译期无法确定,此时可以写轻量包装类同时支持两种访问形式:
#include <iostream> using namespace std; class VbaArray { private: double* _data; int _rows; int _cols; public: VbaArray(double* data, int rows, int cols) : _data(data), _rows(rows), _cols(cols) {} // 支持二维访问 arr(i,j) double& operator()(int row, int col) { return _data[row * _cols + col]; } // 支持一维访问 arr[idx] double& operator[](int idx) { return _data[idx]; } }; int main() { // 模拟数据生成逻辑和之前一致 const int r = 5; const int c = 6; double arr[c][r]={ 1 }; double* arrpt = &arr[0][0]; int i, j, num; num = 0; for (i = 0; i < r; i++ ) { for (j = 0; j < c; j++) { *(arrpt + i +j*r) = (double)num; num++; } } double arr1[r * c]; double* arr1pt = &arr1[0]; for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { *(arr1pt + i*c +j) = *(arrpt + i + j * r); } } // 用包装类访问 VbaArray arr1v(arr1pt, r, c); cout << arr1v(2,3) << endl; // 二维访问 cout << arr1v[2*c +3] << endl; // 一维访问,输出结果与上一行一致 return 0; }
如果需要完全贴合arr[i][j]的语法,可在包装类中重载operator[]返回代理类实现,日常使用operator()的形式已经足够,性能无任何额外开销。
内容的提问来源于stack exchange,提问作者Jim Gunn
相关产品推荐
相关产品推荐

