Как экспортировать тысячи констант в R-пакет? - PullRequest
0 голосов
/ 14 октября 2019

Цель

Я хочу предоставить встроенные константы из разрабатываемого мной пакета, исходящего из исходного кода C, определяемого директивами #define.

Константы OpenGL, определенные как#define директивы

Я обертываю эту библиотеку C GLFW , используя Rcpp. Эта библиотека C, в свою очередь, включает в себя объявления OpenGL, включающие множество #define s, вот небольшой фрагмент из gl.h:

#define GL_T4F_C4F_N3F_V4F          0x2A2D
#define GL_MATRIX_MODE              0x0BA0
#define GL_MODELVIEW                0x1700
#define GL_PROJECTION               0x1701
#define GL_TEXTURE                  0x1702
#define GL_POINT_SMOOTH             0x0B10
#define GL_POINT_SIZE               0x0B11
#define GL_POINT_SIZE_GRANULARITY   0x0B13
#define GL_POINT_SIZE_RANGE         0x0B12
#define GL_LINE_SMOOTH              0x0B20

Обтекание определений макросов C в функциях C ++

Теперь я раскрыл эти определения макросов C, заключив их в функции c ++, например:

// [[Rcpp::export]]
Rcpp::IntegerVector macro_gl_matrix_mode() {return Rcpp::wrap((unsigned int) GL_MATRIX_MODE);}

Экспорт переменных

А затем у меня есть исходный файл R в data-raw/ это, по сути, вызывает те неэкспортируемые функции и сохраняет каждый объект на диск: (сокращенно для ясности):

library(glfw)
library(tibble)
library(usethis)
library(fs)
library(dplyr)

#
# use_data2 accepts a list of strings with the names of the objects to be
# exported instead of the interface provided by usethis::use_data that expects
# multiple arguments passed in `...`.
#
use_data2 <- function(objs,
                      internal = FALSE,
                      overwrite = FALSE,
                      compress = "bzip2",
                      version = 2,
                      envir = parent.frame())
{
  usethis:::check_is_package("use_data()")
  if (internal) {
    usethis::use_directory("R")
    paths <- fs::path("R", "sysdata.rda")
    objs <- list(objs)
  }
  else {
    usethis::use_directory("data")
    paths <- fs::path("data", objs, ext = "rda")
  }
  usethis:::check_files_absent(proj_path(paths), overwrite = overwrite)
  usethis::ui_done("Saving {ui_value(unlist(objs))} to {ui_value(paths)}")
  mapply(save, list = objs,
         file = proj_path(paths),
         MoreArgs = list(envir = envir, compress = compress, version = version)
  )
  invisible()
}

gl <- new.env()

# Begin of loads of assign calls
# (...)
assign('GL_MATRIX_MODE', glfw:::macro_gl_matrix_mode(), envir = gl)
# (...)
# End

#
# Exporting
#

gl_lst <- as.list(gl)
gl_names <- names(gl_lst)

use_data2(gl_names, internal = FALSE, compress = "xz", overwrite = TRUE, version = 2, envir = gl)

Это работает, но у меня 5727 из этих констант для экспорта. Поэтому, когда я загружаю свою посылку, она просто дольше 5 минут загружается на этом этапе:

*** moving datasets to lazyload DB

Так что должен быть лучший способ, верно? Это не только очень медленно во время загрузки пакета, но и я предполагаю, что наличие тысяч объектов в моей папке data/ создаст проблемы с точки зрения стандартов или требований пакета ...

Позвольте мне просто сказать, что я пытался избежать инкапсуляции всех этих констант в список или фрейм данных, потому что я хотел, чтобы интерфейс API был похож на библиотеку C в этом отношении, т. Е. Сейчас я думаю, что довольно приятно иметь возможностьпросто использовать переменные GL_MODELVIEW или GL_POINT_SIZE_GRANULARITY прямо без какого-либо дополнительного синтаксиса.

Любая помощь / указатели приветствуются.

Примечание: Этот другой вопрос похож на мой, но онпока не имеет ответа, и область действия может немного отличаться, потому что мои константы изначально взяты из кода C, поэтому может быть более конкретное решение моей проблемы, например, с использованием Rcpp способом, который я еще не пробовал: Экспорт громоздкого набора констант в пакет .

1 Ответ

0 голосов
/ 14 октября 2019

Я изучаю следующий подход:

Шаг 1

Вместо того, чтобы экспортировать все эти константы отдельно, я собираюсь экспортировать среду, которая инкапсулирует все константы: среда gl (похоже на предложение @ ralf-stubner). Это значительно ускоряет загрузку (перестройку пакета).

Итак, в моем data-raw/gl_macros.R (скрипте генерации данных) я добавляю эту последнюю строку для экспорта среды gl:

usethis::use_data(gl, internal = FALSE, compress = "xz", overwrite = TRUE, version = 2)

Шаг 2

А затем, для удобства доступа к макросам OpenGL с их оригинальными именами, я добавляю хук при подключении к своему R/zzz.R:

.onAttach <- function(libname, pkgname) {
  for (n in ls(glfw::gl, all.names = TRUE)) assign(n, get(n, glfw::gl), .GlobalEnv)
} # .onAttach()

Кажется, работает! По крайней мере, на интерактивной сессии. Этот последний шаг занимает несколько секунд, но это намного быстрее, чем оригинальный подход. Но сейчас я думаю, что это не будет работать, если мой пакет используется другими пакетами, хотя я не уверен.

Альтернатива шагу 2

Возможно, это будет работать лучше:

.onLoad <- function(libname, pkgname) {
  attach(glfw::gl)
} # .onLoad()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...