Портирование буферов символов в Rcpp - PullRequest
0 голосов
/ 22 февраля 2020

Я пытаюсь запустить C код в R, используя R cpp, но не уверен, как преобразовать буфер, используемый для хранения данных из файла. В третьей строке кода ниже я выделяю неподписанный буфер символов, и моя проблема в том, что я не знаю, какой тип данных R cpp использовать. Как только данные будут считаны в буфер, я выяснил, как использовать R cpp :: NumericMatrix для хранения окончательного результата, но не символьного буфера. Я видел несколько ответов Дирка Эддельбюттеля на похожие вопросы, где он предлагает заменить все вызовы 'mallo c' командами инициализации R cpp. Я попытался использовать R cpp :: CharacterVector, но затем в конце l oop есть несоответствие типов: R cpp :: CharacterVector не может быть прочитан как беззнаковый long long int. Код выполняется для некоторых C -компиляторов, но выдает ошибку «повреждение памяти» для других, поэтому я бы предпочел сделать то, что предлагает Дирк (использовать типы данных R cpp), чтобы код работал независимо от того, спецификатор c.

    FILE *fp = fopen( filename, "r" );
    fseek( fp, index_data_offset, SEEK_SET );
    unsigned char* buf = (unsigned char *)malloc( 3 * number_of_index_entries * sizeof(unsigned long long int) );
    fread( buf, sizeof("unsigned long long int"), (long)(3 * number_of_index_entries), fp );
    fclose( fp );

    // Convert "buf" into a 3-column matrix.
    unsigned long long int l;
    Rcpp::NumericMatrix ToC(3, number_of_index_entries);
    for (int col=0; col<number_of_index_entries; col++ ) {
        l = 0;
        int offset = (col*3 + 0)*sizeof(unsigned long long int);
        for (int i = 0; i < 8; ++i) {
            l = l | ((unsigned long long int)buf[i+offset] << (8 * i));
        }
        ToC(0,col) = l;

        l = 0;
        offset = (col*3 + 1)*sizeof(unsigned long long int);
        for (int i = 0; i < 8; ++i) {
            l = l | ((unsigned long long int)buf[i+offset] << (8 * i));
        }
        ToC(1,col) = l;

        l = 0;
        offset = (col*3 + 2)*sizeof(unsigned long long int);
        for (int i = 0; i < 8; ++i) {
            l = l | ((unsigned long long int)buf[i+offset] << (8 * i));
        }
        ToC(2,col) = l;
    }
    return( ToC );

Ответы [ 2 ]

5 голосов
/ 22 февраля 2020

C и C ++ могут быть милыми. Если вы знаете, что делаете, у вас есть прямая линия очень к базовому оборудованию и абстракция более высокого уровня для эффективного рассуждения.

Я бы предложил упростить и уменьшить проблему. Начните с простого и известного случая, например, вектор STL double. Давайте назовем это x. Заполните его 10 или сотнями элементов, затем откройте FILE и напишите блоб из

x.data(),  x.size() * sizeof(double)

Закройте файл. Считайте его в R cpp, сначала выделив NumericVector v того же размера, затем прочитав байты обратно и затем вызвав memcpy в &(v[0]).

Это должен быть тот же вектор.

Тогда вы можете обобщать на разные типы. Поскольку векторы гарантированно являются непрерывной памятью , вы можете напрямую использовать этот трюк сериализации.

Вы можете сделать это с помощью буферов символов, или void*, или ... Ничего из этого не имеет значения до тех пор, пока вы будете осторожны, чтобы не ошибиться . Т.е. не передает int полезную нагрузку на double и т. Д.

Теперь, рекомендуется ли это ? Черт возьми, если вы не гоняетесь за производительностью и достаточно хорошо знаете, что делаете, и в этом случае это разумно. В противном случае положитесь на fantasti c существующих пакетов, таких как fst или qs , чтобы сделать это за вас.

Я надеюсь, что это поможет с вашим вопросом , Я не совсем что это вы спрашивали. Может быть, вы уточнить (и, возможно, сократить / сосредоточиться), если нет.

0 голосов
/ 27 февраля 2020

Типографский прием сделал свое дело:

    Rcpp::NumericVector NumVecBuf( 3 * number_of_index_entries * sizeof(unsigned long long int) );
    unsigned char* buf = (unsigned char*) &(NumVecBuf[0]);

Заявление Дирка о «непрерывной памяти» предположило, что это сработает, поэтому я пошел дальше и отметил его комментарий как ответ. Спасибо, Дирк! И спасибо за разработку и поддержку R cpp!

...