R не будет ссылаться / не может найти скомпилированный загруженный код C

Я создал новую функцию Robust HoltWinters (основанную на методе stats :: Holt-Winters) в R (за «Прочное outlookирование с экспоненциальным сглаживанием холмов и холмов» Сары Гелпер1, Роланд Фрид, Кристоф Крокс, 26 сентября, 2008.) Почему? А почему бы не! Но я отвлекся …

Ядро статистики: метод Holt-Winters – это C-код C_HoltWinters , который я модифицировал, чтобы быть надежным (см. Ниже)

#include  #include  // memcpy #include  #include  #include "ts.h" void HoltWinters ( double *x, /*as.double(x) */ double *x_adj, /*Adjust time series data, if need be Added*/ int *xl, /*lenx - Length of the current time series*/ double *alpha, /*as.double(max(min(alpha, 1), 0)), */ double *beta, /*as.double(max(min(beta,1), 0)), */ double *gamma, /*as.double(max(min(gamma, 1), 0)), */ double *llamda,/*as.double(max(min(llamda,1),0)), ADDED*/ int *start_time, /*as.integer(start.time), */ int *seasonal, /*as.integer(!+(seasonal == "multiplicative")), */ int *period, /* as.integer(f), */ int *dotrend, /* as.integer(!is.logical(beta) || beta), */ int *doseasonal, /* as.integer(!is.logical(gamma) || gamma), */ double *a, /*l.start - starting values for level*/ double *b, /*b.start - starting values for Trend*/ double *s, /*s.start - starting values for SEasonal*/ double *l, /*t.start - starting values for LLamda ADDED*/ double *k, /* Value for K ADDED*/ double *ck, /*value for ck ADDED*/ /* return values */ double *SSE, double *level, double *trend, double *season ) { double res = 0, xhat = 0, stmp = 0, theta = 1, RhoK = 0, phi = 0 ; int i, i0, s0; /*i is the current t, i0 is the current LESS starting period, and s0 = is the seasonal current LESS Starting period*/ /* copy start values to the beginning of the vectors */ level[0] = *a; if (*dotrend == 1) trend[0] = *b; if (*doseasonal == 1) memcpy(season, s, *period * sizeof(double)); for (i = *start_time - 1; i < *xl; i++) { /* indices for period i */ i0 = i - *start_time + 2; s0 = i0 + *period - 1; /* forecast *for* period i */ xhat = level[i0 - 1] + (*dotrend == 1 ? trend[i0 - 1] : 0); stmp = *doseasonal == 1 ? season[s0 - *period] : (*seasonal != 1); if (*seasonal == 1) xhat += stmp; else xhat *= stmp; /* Sum of Squared Errors */ res = x[i] - xhat; /*adjusting for robustness....Gahds*/ RhoK = (abs(res / theta) <= *k ? *ck * (1 - pow(1 - pow((res / (*k * theta)),2),3)): *ck); theta = sqrt(*llamda * RhoK * pow(theta,2) + (1 - *llamda) * pow(theta,2)); phi = (abs(res / theta) < *k ? res / theta : ((res / theta) / abs(res / theta) * (*k))); x_adj[i] = phi * theta + xhat; res = x_adj[i] - xhat; *SSE += res * res; /* estimate of level *in* period i */ if (*seasonal == 1) level[i0] = *alpha * (x_adj[i] - stmp) + (1 - *alpha) * (level[i0 - 1] + trend[i0 - 1]); else level[i0] = *alpha * (x_adj[i] / stmp) + (1 - *alpha) * (level[i0 - 1] + trend[i0 - 1]); /* estimate of trend *in* period i */ if (*dotrend == 1) trend[i0] = *beta * (level[i0] - level[i0 - 1]) + (1 - *beta) * trend[i0 - 1]; /* estimate of seasonal component *in* period i */ if (*doseasonal == 1) { if (*seasonal == 1) season[s0] = *gamma * (x_adj[i] - level[i0]) + (1 - *gamma) * stmp; else season[s0] = *gamma * (x_adj[i] / level[i0]) + (1 - *gamma) * stmp; } } } 

Поэтому я скомпилирую его во вздохе Windows с помощью R (3.2.2):

 R CMD SHLIB C_R_HoltWinters.c gcc -m64 -I"C:/PROGRA~1/R/R-32~1.2/include" -DNDEBUG -I"d:/RCompile/r-compiling/local/local320/include" -O2 -Wall -std=gnu99 -mtune=core2 -c C_R_HoltWinters.c -o C_R_HoltWinters.o gcc -m64 -shared -s -static-libgcc -o C_R_HoltWinters.dll tmp.def C_R_HoltWinters.o -Ld:/RCompile/r-compiling/local/local320/lib/x64 -Ld:/RCompile/r-compiling/local/local320/lib -LC:/PROGRA~1/R/R-32~1.2/bin/x64 -lR 

Загрузите его в R:

 dyn.load('C_R_HoltWinters.dll') 

Проверяя, есть ли там

  > getLoadedDLLs() Filename Dynamic.Lookup base base FALSE utils C:/Program Files/RRO/R-3.2.2/library/utils/libs/x64/utils.dll FALSE methods C:/Program Files/RRO/R-3.2.2/library/methods/libs/x64/methods.dll FALSE RevoUtilsMath C:/Program Files/RRO/R-3.2.2/library/RevoUtilsMath/libs/x64/RevoUtilsMath.dll TRUE grDevices C:/Program Files/RRO/R-3.2.2/library/grDevices/libs/x64/grDevices.dll FALSE graphics C:/Program Files/RRO/R-3.2.2/library/graphics/libs/x64/graphics.dll FALSE stats C:/Program Files/RRO/R-3.2.2/library/stats/libs/x64/stats.dll FALSE tools C:/Program Files/RRO/R-3.2.2/library/tools/libs/x64/tools.dll FALSE internet C:/PROGRA~1/RRO/R-32~1.2/modules/x64/internet.dll TRUE (embedding) (embedding) FALSE C_R_HoltWinters C:/scripts/R/C_R_HoltWinters.dll TRUE 

Ах, да, вот оно. Итак, просто для пупсов и хихиканья я запускаю на нем тест:

  > is.loaded('C_R_HoltWinters') [1] FALSE > is.loaded("C_R_HoltWinters") [1] FALSE > is.loaded(C_R_HoltWinters) Error in is.loaded(C_R_HoltWinters) : object 'C_R_HoltWinters' not found 

Хорошо … он должен быть там, но это не так. Может быть, он знает что-то, чего я не делаю, поэтому я пытаюсь запустить его:

 > .C("C_R_HoltWinters", blahblahblah) Error in .C("C_R_HoltWinters") : C symbol name "C_R_HoltWinters" not in load table > .Call("C_R_HoltWinters", blahblahblah) Error in .Call("C_R_HoltWinters") : C symbol name "C_R_HoltWinters" not in load table 

Но когда я загружаю другой c-код под названием foo и запускаю его, он работает нормально.

Почему R не может ссылаться на C_R_HoltWinters.dll? Это также сломается, если я положу его в пакет?

Спасибо

    Хорошо, проблема здесь в том, что это путаница между именами символов (которые могут представлять собой функции в C) и разделяемой библиотекой. После запуска dyn.load('C_R_HoltWinters.dll') вы можете проверить, что он был загружен, посмотрев на getLoadedDlls() . Теперь, что is.loaded ищет, являются символами, которые определены внутри этой DLL. Таким образом, следующий код покажет вам, что функция «HoltWinters», определенная в вашем C-коде, доступна для вызова из R:

     > is.loaded("HoltWinters") [1] TRUE 

    И это имя функции, которое вы также должны использовать для вызовов .C.