Skip to content

Commit afce3c6

Browse files
committed
Exposing RcppTskit_treeseq_xptr in a header for #40 plus polish
1 parent 3081524 commit afce3c6

6 files changed

Lines changed: 62 additions & 49 deletions

File tree

RcppTskit/DESCRIPTION

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ Depends:
3030
Imports:
3131
methods,
3232
R6,
33-
Rcpp (>= 1.1.0),
34-
reticulate
33+
Rcpp (>= 0.12.10),
34+
reticulate (>= 1.41.0)
3535
Suggests:
3636
covr,
3737
knitr,
3838
quarto,
3939
spelling,
4040
testthat (>= 3.0.0)
4141
LinkingTo:
42-
Rcpp (>= 1.1.0)
42+
Rcpp (>= 0.12.10)
4343
VignetteBuilder:
4444
quarto
4545
Config/testthat/edition: 3

RcppTskit/R/RcppTskit.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
#' to avoid importing the module repeatedly, if it has been imported already
1818
#' in which case we use that imported module. Since this process can be
1919
#' finicky (it depends on the availability of reticulate Python, module already
20-
#' instaled, internet access, etc.)
20+
#' installed, internet access, etc.)
2121
#' @return \code{get_tskit_py} returns \code{tskit} a reticulate Python module
22-
#' if succesful or otherwise throws an error (when \code{object_name} exists
22+
#' if successful or otherwise throws an error (when \code{object_name} exists
2323
#' but is not a reticulate Python module) or returns \code{simpleError}
2424
#' (when installation or import failed). \code{check_tskit_py} returns
2525
#' \code{TRUE} if \code{object} is a reticulate Python module or \code{FALSE}
@@ -52,7 +52,7 @@ get_tskit_py <- function(object_name = "tskit", force = FALSE) {
5252
}
5353
}
5454

55-
msgSuccess <- paste0('reticulate::py_require("', object_name, '") succeded!')
55+
msgSuccess <- paste0('reticulate::py_require("', object_name, '") succeeded!')
5656
msgFail <- paste0('reticulate::py_require("', object_name, '") failed!')
5757
e <- simpleError(msgFail)
5858
if (!reticulate::py_module_available(object_name)) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef RCPPTSKIT_H
2+
#define RCPPTSKIT_H
3+
4+
#include <Rcpp.h>
5+
#include <tskit.h>
6+
7+
// Finaliser to free tsk_treeseq_t when it is garbage collected
8+
// See \url{https://tskit.dev/tskit/docs/stable/c-api.html#c.tsk_treeseq_free}
9+
// for more details.
10+
static void RcppTskit_treeseq_xptr_delete(tsk_treeseq_t *ptr) {
11+
if (ptr != NULL) {
12+
tsk_treeseq_free(ptr);
13+
delete ptr;
14+
}
15+
}
16+
17+
// Define the external pointer type for tsk_treeseq_t with the finaliser
18+
using RcppTskit_treeseq_xptr = Rcpp::XPtr<tsk_treeseq_t, Rcpp::PreserveStorage,
19+
RcppTskit_treeseq_xptr_delete, true>;
20+
21+
#endif

RcppTskit/man/get_tskit_py.Rd

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

RcppTskit/src/RcppTskit.cpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,4 @@
1-
#include <Rcpp.h>
2-
#include <tskit.h>
3-
4-
// using namespace Rcpp; // to omit Rcpp:: prefix for whole Rcpp API
5-
// using Rcpp::IntegerVector; // to omit Rcpp:: prefix for IntegerVector
6-
7-
// Finaliser to free tsk_treeseq_t when it is garbage collected
8-
// See \url{https://tskit.dev/tskit/docs/stable/c-api.html#c.tsk_treeseq_free}
9-
// for more details.
10-
static void RcppTskit_treeseq_xptr_delete(tsk_treeseq_t *ptr) {
11-
if (ptr != NULL) {
12-
tsk_treeseq_free(ptr);
13-
delete ptr;
14-
}
15-
}
16-
// Define the external pointer type for tsk_treeseq_t with the finaliser
17-
using RcppTskit_treeseq_xptr = Rcpp::XPtr<tsk_treeseq_t, Rcpp::PreserveStorage,
18-
RcppTskit_treeseq_xptr_delete, true>;
1+
#include <RcppTskit.hpp>
192

203
//' @title Report the version of installed kastore C API
214
//' @details The version is stored in the installed header \code{kastore.h}.

RcppTskit/vignettes/RcppTskit_intro.qmd

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -157,16 +157,20 @@ after we describe the implemented data and class model.
157157

158158
## Data and class model
159159

160-
`RcppTskit` represents a tree sequence as a lightweight R object of R6 class `TreeSequence`.
161-
R6 class was partially chosen so the R code calls resemble Python code.
162-
`TreeSequence` wraps an external pointer (`externalptr`) to the `tskit`
163-
C data structure (`tsk_treeseq_t`).
164-
Most methods (for example, `ts$num_individuals()`, `ts$dump()`, etc.)
160+
`RcppTskit` represents a tree sequence as a lightweight R6 object of class `TreeSequence`.
161+
The R6 class was chosen in part so that `TreeSequence` method calls in R
162+
resemble the tskit Python API.
163+
`TreeSequence` wraps an external pointer (`externalptr`) to
164+
the `tskit` C object structure `tsk_treeseq_t`.
165+
Most methods (for example, `ts$num_individuals()` and `ts$dump()`)
165166
call the `tskit` C API via `Rcpp`,
166-
so the calls are fast and the object is not copied
167-
unless you explicitly write/read or change it.
167+
so calls are fast and the object is not copied
168+
unless you explicitly modify it.
168169
The underlying pointer is exposed as `TreeSequence$pointer`
169-
for developers and advanced users that can write C++ code.
170+
for developers and advanced users who work with C++.
171+
In C++, the pointer has type `RcppTskit_treeseq_xptr`,
172+
and the tree sequence memory is released by the `Rcpp::XPtr`
173+
finaliser when the pointer is garbage-collected in R.
170174

171175
## For typical use cases
172176

@@ -256,9 +260,9 @@ ts$num_individuals() # 2 (if you have ran the above Python code)
256260
#| label: use_case_3
257261
# Write a C++ function as multi-line character string
258262
codeString <- '
259-
#include <tskit.h>
263+
#include <RcppTskit.hpp>
260264
int ts_num_individuals(SEXP ts) {
261-
Rcpp::XPtr<tsk_treeseq_t> ts_xptr(ts);
265+
RcppTskit_treeseq_xptr ts_xptr(ts);
262266
return (int) tsk_treeseq_get_num_individuals(ts_xptr);
263267
}'
264268
@@ -285,28 +289,33 @@ ts$num_individuals()
285289

286290
### 4) Call `tskit` C API in C++ code in another R package
287291

288-
To call the `tskit` C API in your own R package via `Rcpp` you can leverage `RcppTskit`.
289-
Just follow the steps below and check how these were implemented in
290-
the test R package `RcppTskitTestPkgLinkingTo` at TODO.
292+
To call the `tskit` C API in your own R package via `Rcpp`
293+
you can leverage `RcppTskit`, which will simplify your installation
294+
and enable you to quickly call
295+
To do this, follow the steps below and check how these were implemented in
296+
the test R package `RcppTskitTestLinkingTo` at https://github.com/HighlanderLab/RcppTskitTestLinking.
291297

292-
a) Open `DESCRIPTION` file and add `RcppTskit` to the `LinkingTo:` field,
293-
TODO: likely also `Imports:` field.
298+
a) Open `DESCRIPTION` file and
299+
add `RcppTskit` to the `Imports:` and `LinkingTo:` field, and further
300+
add `Rcpp` to `LinkingTo:` field as a minimum.
294301

295-
TODO: And Rcpp too?
302+
b) Create `R/YourPackage-package.R` file and add to it at a minimum:
303+
`#' @import RcppTskit` in one line and `"_PACKAGE"` in another line,
304+
so that `devtools` will manage your package `NAMESPACE` imports.
296305

297-
b) Add `#include <tskit.h>` as needed to your C++ header files in `src` directory.
306+
c) Add `#include <RcppTskit.hpp>` as needed to your C++ header files in `src` directory.
298307

299-
c) Add `// [[Rcpp::depends(RcppTskit)]]` to your C++ files in `src` directory.
308+
d) Add `// [[Rcpp::depends(RcppTskit)]]` to your C++ files in `src` directory.
300309

301-
d) Add `// [[Rcpp::plugins(RcppTskit)]]` to your C++ files in `src` directory.
310+
e) Add `// [[Rcpp::plugins(RcppTskit)]]` to your C++ files in `src` directory.
302311

303-
e) Call `tskit` C API as needed in your C++ code in `src` directory.
312+
f) Call `RcppTskit` C++ API and `tskit` C API as needed in your C++ files in `src` directory.
304313

305-
f) Configure your package build to use the `RcppTskit` library file
314+
g) Configure your package build to use the `RcppTskit` library file
306315
with the following steps:
307316

308317
- Add `src/Makevars.in` and `src/Makevars.win.in` files with
309-
`PKG_LIB = @RCPPTSKIT_LIB@` flag, in addition to other flags.
318+
`PKG_LIBS = @RCPPTSKIT_LIB@` flag, in addition to other flags.
310319

311320
- Add `tools/configure.R` file,
312321
which will replace `@RCPPTSKIT_LIB@` in `src/Makevars.in` and `src/Makevars.win.in`
@@ -319,7 +328,7 @@ f) Configure your package build to use the `RcppTskit` library file
319328
- Add `cleanup` and `cleanup.win` scripts (and make them executable)
320329
to remove `src/Makevars` and `src/Makevars.win` as well as compilation files.
321330

322-
g) You should now be ready to build, check, and install your package using
331+
h) You should now be ready to build, check, and install your package using
323332
`devtools::build()`, `devtools::check()`, and `devtools::install()`
324333
or their `R CMD` equivalents.
325334

0 commit comments

Comments
 (0)