Недавно я экспериментировал с Rcpp (inline) для генерации библиотек DLL, которые выполняют различные задачи на поставляемых R входах. Я хотел бы иметь возможность отлаживать код в этих DLL строк за строкой, учитывая определенный набор R-входов. (я работаю под Windows.)
Чтобы проиллюстрировать, рассмотрим конкретный пример того, что любой человек должен иметь возможность запускать...
Код ниже - это действительно простая функция cxx, которая просто удваивает входной вектор. Однако обратите внимание, что есть дополнительная переменная myvar
, которая несколько раз меняет значение, но не влияет на вывод - это было добавлено, чтобы мы могли видеть, когда процесс отладки работает правильно.
library(inline)
library(Rcpp)
f0 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='
Rcpp::NumericVector xa(a);
int myvar = 19;
int na = xa.size();
myvar = 27;
Rcpp::NumericVector out1(na);
for(int i=0; i < na; i++) {
out1[i] = 2*xa[i];
myvar++;
}
myvar = 101;
return(Rcpp::List::create( _["out1"] = out1));
')
После выполнения описанного выше введите команду
getLoadedDLLs()
выводит список DLL в сеансе R. Последний, указанный в списке, должен быть DLL, созданный вышеуказанным процессом, - он имеет случайное временное имя, которое в моем случае
file7e61645c
В столбце "Filename" указано, что cxxfunction поместил эту DLL в папку tempdir()
, которая для меня в настоящее время
C:/Users/TimP/AppData/Local/Temp/RtmpXuxtpa/file7e61645c.dll
Теперь очевидным способом вызова DLL является f0
, как показано ниже:
> f0(c(-7,0.7,77))
$out1
[1] -14.0 1.4 154.0
Но мы можем, конечно, также вызвать DLL напрямую по имени с помощью команды .Call
:
> .Call("file7e61645c",c(-7,0.7,77))
$out1
[1] -14.0 1.4 154.0
Итак, я дошел до того, что я вызываю отдельную DLL напрямую с помощью R-входа (здесь, вектор c(-7,0.7,77)
) и вернул ответ правильно в R.
Я действительно нуждаюсь в том, что это средство для линейной отладки (используя gdb, я полагаю), что позволит мне наблюдать за значением myvar
, установленным в 19, 27, 28, 29, 30 и, наконец, 101 по мере продвижения кода. Приведенный выше пример намеренно настроен таким образом, что вызов DLL ничего не сообщает нам о myvar.
Чтобы уточнить, "условие выигрыша" здесь может наблюдать изменение myvar (видение myvar = 19 будет первым шагом!), не добавляя ничего в тело кода. Это, очевидно, может потребовать внесения изменений в способ компиляции кода (есть ли настройки режима отладки для включения?) Или способ вызова R, но я не знаю с чего начать. Как отмечалось выше, все это основано на Windows.
Заключительное примечание. В моих экспериментах я фактически внес некоторые незначительные изменения в копию cxxfunction, чтобы выходная DLL и код внутри нее получали пользовательское имя и находились в пользовательском каталоге, а не временное имя и местоположение. Но это не влияет на суть вопроса. Я упоминаю это только для того, чтобы подчеркнуть, что довольно легко изменить настройки компиляции, если кто-то дает мне толчок:)
Для полноты установки verbose = TRUE в исходном вызове cxxfunction выше аргумент компиляции имеет следующий вид:
C:/R/R-2.13.2/bin/i386/R CMD SHLIB file7e61645c.cpp 2> file7e61645c.cpp.err.txt
g++ -I"C:/R/R-213~1.2/include" -I"C:/R/R-2.13.2/library/Rcpp/include" -O2 -Wall -c file7e61645c.cpp -o file7e61645c.o
g++ -shared -s -static-libgcc -o file7e61645c.dll tmp.def file7e61645c.o C:/R/R-2.13.2/library/Rcpp/lib/i386/libRcpp.a -LC:/R/R-213~1.2/bin/i386 -lR
У моей адаптированной версии есть аргумент компиляции, идентичный приведенному выше, за исключением того, что строка "file7e61645c" заменяется везде выбором пользователя (например, "testdll" ) и соответствующими файлами, скопированными в более постоянное место.
Заранее спасибо за помощь ребятам:)