Извлечь long [] из объекта R - PullRequest
2 голосов
/ 15 февраля 2011

Я пытаюсь создать оболочку для некоторого кода обработки разреженной матрицы на основе C (см. предыдущий вопрос ). Чтобы вызвать функцию C рабочей лошадки, мне нужно создать структуру, которая выглядит следующим образом:

struct smat {
  long rows;
  long cols;
  long vals;     /* Total non-zero entries. */
  long *pointr;  /* For each col (plus 1), index of first non-zero entry. */
  long *rowind;  /* For each nz entry, the row index. */
  double *value; /* For each nz entry, the value. */
};

Они хорошо соответствуют слотам в dgCMatrix разреженной матрице. Поэтому в идеале я бы просто указал на внутренние массивы в dgCMatrix (после проверки, что функция C не будет вертеться с данными [что я еще не сделал]).

Для *value похоже, что я смогу использовать REALSXP или что-то еще, чтобы получить double[] по желанию. Но для *pointr и *rowind я не уверен, что лучший способ получить соответствующий массив. Нужно ли будет циклически проходить через записи и копировать их в новые массивы, приводя их в процессе записи? Или Rcpp может дать здесь немного сахара? Это первый раз, когда я действительно много использую Rcpp, и я еще не очень разбираюсь в этом.

Спасибо.

Редактировать: У меня также есть некоторые проблемы со связыванием, которые я не понимаю:

Error in dyn.load(libLFile) : 
  unable to load shared object '/var/folders/TL/TL+wXnanH5uhWm4RtUrrjE+++TM/-Tmp-//RtmpAA9upc/file2d4606aa.so':
  dlopen(/var/folders/TL/TL+wXnanH5uhWm4RtUrrjE+++TM/-Tmp-//RtmpAA9upc/file2d4606aa.so, 6): Symbol not found: __Z8svdLAS2AP4smatl
  Referenced from: /var/folders/TL/TL+wXnanH5uhWm4RtUrrjE+++TM/-Tmp-//RtmpAA9upc/file2d4606aa.so
  Expected in: flat namespace
 in /var/folders/TL/TL+wXnanH5uhWm4RtUrrjE+++TM/-Tmp-//RtmpAA9upc/file2d4606aa.so

Нужно ли создавать библиотеку с некоторыми специальными флагами компиляции?

Редактировать 2: похоже, что мой параметр libargs не имеет никакого эффекта, поэтому символы libsvd никогда не попадают в библиотеку. Я не могу найти способ включить библиотеки, используя cxxfunction() - вот что я попробовал, но дополнительные параметры (желаемое, с большой долей заимствования из cfunction()) молча сожрали:

fn <- cxxfunction(sig=c(nrow="integer", mi="long", mp="long", mx="numeric"), 
                  body=code,
                  includes="#include <svdlib.h>\n", 
                  cppargs="-I/Users/u0048513/Downloads/SVDLIBC", 
                  libargs="-L/Users/u0048513/Downloads/SVDLIBC -lsvd", 
                  plugin="Rcpp",
                  verbose=TRUE)

Мне кажется, что я все делаю неправильно, потому что ничего не работает. Кто-нибудь пнул меня в правильном направлении?

Ответы [ 2 ]

1 голос
/ 28 февраля 2011

Я решил также разместить запрос в списке рассылки Rcpp-devel и получил несколько полезных советов и помощи от Дирка и Дуга:

http://lists.r -forge.r-project.org / pipermail / rcpp-разви / 2011-февраль / 001851.html

Я все еще не супер-легок в этом, но добираюсь. =)

0 голосов
/ 21 февраля 2011

В прошлом году я сделал нечто подобное для интерфейса [R] -Smalltalk и сделал его более общим, чтобы иметь возможность передавать все данные назад и вперед с помощью байтовых массивов:

В C у меня есть:

DLLIMPORT void getLengthOfNextMessage(byte* a);
DLLIMPORT void getNextMessage(byte* a);

В R:

getLengthOfNextMessage <- function() {
    tmp1  <- as.raw(rep(0,4))
    tmp2<-.C("getLengthOfNextMessage", tmp1)
    return(bvToInt(tmp2))
}

receiveMessage <- function() {
    #if(getNumberOfMessages()==0) {
    #   print("error: no messages")
    #   return();
    #}
    tmp1<-as.raw(rep(0, getLengthOfNextMessage()+getSizeOfMessages()))
    tmp2<-.C("getNextMessage", tmp1)
    msg<-as.raw(tmp2[[1]])
        print(":::confirm received")
        print(bvToInt(msg[13:16]))
    # confirmReceived(bvToInt(msg[13:16]))
    return(msg)
}

Я прокомментировал использование функций getNumberOfMessages () и подтвердитеReceived (), которые являются специфическими для проблемы, которую мне пришлось решить (многократная передача туда и обратно). По сути, код использует байтовый массив аргумента для передачи информации, сначала 4-байтовой длинной информации, а затем фактических данных. Это кажется менее элегантным (даже для меня), чем использование структур, но я обнаружил, что это более универсально, и я могу подключиться к любому dll, передав любой тип данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...