c++cvectorsgxenclave

Best way to convert 2D vector to C type (for SGX enclave)


I'm trying to write an SGX enclave that takes in a 2D vector of int (representing a grayscale image), but edger8r accepts only C types.

I am aware of this and this, but could someone provide an example on how to transform a type like:

vector< vector <int> > ImagePixels;

into a C type so that I can pass it to an SGX enclave?


Solution

  • std::vector has a data() method that will give you a plain pointer to its data. However, you'll need to do something with that second layer of vectors, so you'll need to create a temporary array that will store a list of plain pointers from the inner vector.

    #include <algorithm>
    #include <iostream>
    #include <vector>
    
    
    extern "C" int my_c_function(int **double_pointer, int rows, int cols) {
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                printf("%d ", double_pointer[i][j]);
            }
            printf("\n");
        }
    }
    
    
    int main() {
        std::vector<std::vector<int>> ImagePixels{{1, 2, 3}, {4, 5, 6}};
    
        // transform a vector of vectors into a vector of pointers
        std::vector<int*> ptrs(ImagePixels.size());
        std::transform(begin(ImagePixels), end(ImagePixels), begin(ptrs),
            [](std::vector<int> &inner_vec) {
                return inner_vec.data();
            });
    
        my_c_function(ptrs.data(), ImagePixels.size(), ImagePixels[0].size());
    }
    

    Live example: https://onlinegdb.com/BJvb3yG3f

    However, if you have control of the entire code, I would suggest using a flat structure, where you just store the whole picture into a falt std::vector<int> row-by-row. You could even do a simple wrapper around std::vector to make it easier to manipulate such a structure:

    class image {
    public:
        image(int rows = 0; int cols = 0)
            : rows_{rows}, cols_{cols}, data_(rows * cols) {}
    
        int &operator ()(int row, int col) {
            return data_[row * cols_ + col];
        }
    
        int *data() { return data_.data(); };
    
        // needs a few more utilities and constant versions of the methods
    private:
        std::vector<int> data_;
        int rows_;
        int cols_;
    };
    

    Then you can do:

    image im(3, 2);
    // set pixels
    im(0, 0) = 1;
    im(0, 1) = 2;
    int *d = im.data(); // a plain pointer to an array of data