Global symbol visibility / deriving from a C++ class defined in a different shared library
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 30/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Stale
- Domain
- developer-experience
Research direction
Start with the cpp_source() entry point and the package shared-library loading behavior described in the issue, comparing it with dyn.load(..., local=FALSE). Determine how cpp11 could make the abstract base class's vtable and RTTI symbols visible to externally compiled C++ implementations. Done means users can derive from the interface through cpp_source() without manually loading the package library.
Written by the indexing model from the issue text.
Description
In my R package based on cpp11, I defined an interface (on the C++ side) as an abstract base class, i.e. a class that has a bunch of virtual functions. When I implement that interface in the same package (meaning I derive from the base class and override some virtual methods) everything works great.
If users need implementations of that interface beyond what my package provides, they can currently do so purely in R; this works by having one particular implementation of the interface that forwards all calls to user-definable R functions. This works nicely, but it rather slow because it requires a round trip from C++ to R and back to C++ for every invocation.
So it would be nice if users could also use cpp_source() to define their own implementations of the interface directly in C++. For that to work, however, the shared object created by cpp_soure() has to be able to see the symbols for the vtable and RTTI information of the abstract base class. Unfortunately, however, it seems that doing require(my_library) loads the shared library in way that does not make its symbols globally visible. So when I try to implement the interface with cpp_source(), I get an "undefined symbol" error for the RTTI information (i.e. typeinfo) of the abstract base class. This happens even if my code doesn't explicitly use RTTI btw -- the presence of virtual functions is enough for the compiler to generate references to this symbol it seems.
The only workaround I've managed to find for this is to manually load the shared library of my package with dyn.load(..., local=FALSE) before doing library(my_package). So currently I have to tell users to include this rather dirty snippet of code in their scripts:
nnR.dir <- find.package("my_package")
nnR.lib <- if (nzchar(.Platform$r_arch)) {
file.path(nnR.dir, "libs", .Platform$r_arch, paste0("NEXTNetR", .Platform$dynlib.ext))
} else {
file.path(nnR.dir, "libs", paste0("my_package", .Platform$dynlib.ext))
}
dyn.load(nnR.lib, local=FALSE, now=TRUE)
It would be great if cpp11 could simplify this somewhat, and e.g. provide a way to export symbols globally the same way that manually loading dyn.load(..., local=FALSE) does.
- Dominant language
- C++
- Stars
- 224
- Forks
- 52
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from r-lib/cpp11
-
Difficulty 3/5 1-2 days Newbie friendliness 35/100
-
Difficulty 3/5 1-2 days Newbie friendliness 48/100
-
Difficulty 5/5 Over a week Newbie friendliness 20/100
-
Difficulty 3/5 1-2 days Newbie friendliness 42/100
-
Difficulty 3/5 1-2 days Newbie friendliness 45/100
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
AXERA-TECH/ax-llm#77 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
games-on-whales/wolf#509 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
bug-unconfirmed
Difficulty 2/5 1-3 hours Newbie friendliness 76/100