{"id":20942482,"url":"https://github.com/bdilday/embedr","last_synced_at":"2026-05-21T03:02:17.211Z","repository":{"id":78136144,"uuid":"131729015","full_name":"bdilday/embedr","owner":"bdilday","description":null,"archived":false,"fork":false,"pushed_at":"2018-05-03T01:54:27.000Z","size":144,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-02T12:36:44.543Z","etag":null,"topics":["dlang","r"],"latest_commit_sha":null,"homepage":null,"language":"D","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bdilday.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-01T15:23:31.000Z","updated_at":"2018-05-03T01:54:28.000Z","dependencies_parsed_at":"2023-03-03T11:00:26.647Z","dependency_job_id":null,"html_url":"https://github.com/bdilday/embedr","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bdilday/embedr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdilday%2Fembedr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdilday%2Fembedr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdilday%2Fembedr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdilday%2Fembedr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bdilday","download_url":"https://codeload.github.com/bdilday/embedr/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdilday%2Fembedr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33286663,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-21T02:57:32.698Z","status":"ssl_error","status_checked_at":"2026-05-21T02:57:31.990Z","response_time":62,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dlang","r"],"created_at":"2024-11-18T23:27:24.446Z","updated_at":"2026-05-21T03:02:17.161Z","avatar_url":"https://github.com/bdilday.png","language":"D","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Overview\n\nD is a nice programming language, but I make my living doing econometrics, and there aren't many econometrics libraries for D. R has many libraries for econometrics, statistics, data transformation, and just about anything you want to do with data. One solution would be to port all of R's libraries to D. With a few million programmer hours, you could get a good start on that task. This package takes the alternative approach of facilitating communication between D and R. This can be done in two ways:\n\n**Calling D functions from R.** The main program is written in R, but bottlenecks and anything for which D is better are written in D. The D functions are then compiled into a shared library and loaded into R. This procedure is commonly used to call C, C++, and Fortran code from R. This approach has the advantage that an R user can call D functions without knowing anything about D. There is currently support for Linux using DMD and Windows using LDC. LDC support for Linux and Mac will be added in the future.\n\n**Calling R functions from D.** You can use the excellent [RInside](https://github.com/eddelbuettel/rinside) to embed an R interpreter inside your D program. Data is passed efficiently because everything in R is a C struct (SEXPREC). These SEXPREC structs are allocated in either D or R and pointers to them are passed between the two languages. The advantage of this approach is that all of R is available to D programs. There is currently support only for Linux using DMD. I plan to support Windows and Mac as well as the other compilers in the future. Note that Docker works well on Windows and Mac, and I've got a Dockerfile and an explanation of how to use it [here](https://lancebachmeier.com/embedr/dockerusage.html).\n\n# Linux Installation (calling D functions from R)\n\nIf you only want to call D functions from R, installation is easy.\n\n1\\. Install R and the [dmd compiler](http://dlang.org/download.html) (obvious, I know, but I just want to be sure). I recommend updating to the latest version of R.\n2\\. Install the embedr package using devtools:\n\n```\ninstall_bitbucket(\"bachmeil/embedr\")\n```\n\nThat is it. If you have a standard installation (i.e., as long as you haven't done something strange to cause libR.so to be hidden in a place the system can't find it) you are done.\n\n# Linux Installation (calling R functions from D)\n\nEmbedding R inside D requires you to install a slightly modified version of the RInside package in addition to everything above.\n\n1\\. Install R and the [dmd compiler](http://dlang.org/download.html) (obvious, I know, but I just want to be sure). I recommend updating to the latest version of R.  \n2\\. Install [RInsideC](https://bitbucket.org/bachmeil/rinsidec) using devtools. In R:\n    \n```\nlibrary(devtools)\ninstall_bitbucket(\"bachmeil/rinsidec\")\n```\n    \n3\\. Install the embedr package using devtools:\n\n```\ninstall_bitbucket(\"bachmeil/embedr\")\n```\n\nThat is it. If you have a standard installation (i.e., as long as you haven't done something strange to cause libR.so to be hidden in a place the system can't find it) you are done.\n\n# Windows Installation (calling D functions from R)\n\nThis is a little trickier for a variety of reasons. The only recommended\napproach at this time is to let the embedr package install the LDC\ncompiler and do the configuration for you.\n\n1\\. Install R. I recommend updating to the latest version of R.  \n2\\. Install the embedr package using devtools:\n\n```\nlibrary(devtools)\ninstall_bitbucket(\"bachmeil/embedr\")\n```\n    \n3\\. Install the LDC compiler and configure everything:\n\n```\nlibrary(embedr)\nldc.install()\nembedr.configure()\n```\n\nYou should be done at this point. I cannot guarantee that, however, due\nto problems with directories being changed by Windows to read-only status.\n\n# Examples: Calling D Functions From R\n\nNote that Windows requires an explicit export attribute when defining a\nfunction that is to be included as part of a shared library. I present\nboth versions of the simple example to clarify that, but for the other examples\nyou will have to add the export attribute. There are some other differences\nin the Linux and Windows versions. These are due to the fact that those\nfunctions were created at different times, and I have not yet had time\nto make things consistent. I will eventually get around to doing that.\n\n# Simple Example (Linux)\n\nSave this code in a file called librtest.d:\n\n```\nextern(C) {\n  Robj add(Robj rx, Robj ry) {\n    double result = rx.scalar + ry.scalar;\n    return result.robj;\n  }\n}\n```\n\nThen in R, from the same directory as librtest.d, create and load the\nshared library using the `dmd` function:\n\n```\ncompileFile(\"librtest.d\", \"rtest\")\n```\n\nTest it out:\n\n```\n.Call(\"add\", 2.5, 3.65)\n```\n\n# Simple Example (Windows)\n\nThe same thing can be achieved in Windows as follows. Save this code in\nlibrtest.d:\n\n```\nimport embedr.r;\nmixin(createRLibrary(\"rtest\"));\n\nexport extern(C) {\n  Robj add(Robj rx, Robj ry) {\n    double result = rx.scalar + ry.scalar;\n    return result.robj;\n  }\n}\n```\n\nIn the same directory as librtest.d, create and load the DLL:\n\n```\nldc(\"librtest\")\n```\n\nTest it out:\n\n```\n.Call(\"add\", 2.5, 3.65)\n```\n\n# Explanation of the Simple Example\n\nTo come...\n\n\n\n# Embedding R Inside D\n\nThe examples that follow work on Linux, but are for embedding R inside D.\n\n# Hello World\n\nLet's start with an example that has R print \"Hello, World!\" to the screen. Put the following code in a file named hello.d:\n\n```\nimport embedr.r;\n\nvoid main() {\n\tevalRQ(`print(\"Hello, World!\")`);\n}\n```\n\nIn the directory containing hello.d, run the following in R:\n\n```\nlibrary(embedr)\ndmd(\"hello\")\n```\n\nThis will tell dmd to compile your file, handling includes and linking for you, and then run it for you. You should see \"Hello, World!\" printed somewhere. The other examples are the same: save the code in a .d file, then call the dmd function to compile and run it.\n\n# Using Dub\n\nI do not normally use Dub. However, many folks do, and if you want to\nadd dependencies on other libraries like Mir, you don't have much choice\nbut to use Dub.\n\nHere's the dub.sdl file I used to compile the Hello World example above:\n\n```\nname \"myproject\"\ndescription \"embedr hello world\"\nauthors \"lance\"\ncopyright \"Copyright 2018, lance\"\nlicense \"GPLv2\"\nversions \"r\" \"standalone\"\nlflags \"/usr/lib/libR.so\" \"/usr/local/lib/R/site-library/RInsideC/lib/libRInside.so\"\n```\n\nThe `lflags` paths may be different on your machine, and they definitely\nwill be different if you're not using Linux.\n\n# Passing a Matrix From D to R\n\nLet's write a program that tells R to allocate a (2x2) matrix, fills the elements in D, and prints it out in both D and R.\n\n```\nimport embedr.r;\n\nvoid main() {\n\tauto m = RMatrix(2,2);\n\tm[0,0] = 1.5;\n\tm[0,1] = 2.5;\n\tm[1,0] = 3.5;\n\tm[1,1] = 4.5;\n\tm.print(\"Matrix allocated by R, but filled in D\");\n}\n```\n\n`RMatrix` is a struct that holds a pointer to an R object plus the dimensions of the matrix. When the constructor is called with two integer arguments, it has R allocate a matrix with those dimensions.\n\nThe library includes some basic functionality for working with `m`, including getting and setting elements, and printing. Alternatively, we could have passed `m` to R and told R to print it:\n\n```\nimport embedr.r;\n\nvoid main() {\n\tauto m = RMatrix(2,2);\n\tm[0,0] = 1.5;\n\tm[0,1] = 2.5;\n\tm[1,0] = 3.5;\n\tm[1,1] = 4.5;\n  m.toR(\"mm\"); // Now there is an object inside R called mm\n  evalRQ(`print(mm)`);\n```\n\n# Passing a Matrix From R to D\n\nWe can also pass a matrix in the opposite direction. Let's allocate and fill a matrix in R and then work with it in D.\n\n```\nimport embedr.r;\n\nvoid main() {\n  // Generate a (20x5) random matrix in R\n  evalRQ(`m \u003c- matrix(rnorm(100), ncol=5)`);\n  \n  // Create an RMatrix struct in D that holds a pointer to m\n  auto dm = RMatrix(\"m\");\n  dm.print(\"This is a matrix that was created in R\");\n  \n  // Change one element and verify that it has changed in R\n  dm[0,0] = dm[0,0]*4.5;\n  printR(\"m\");\n}\n```\n\nA comment on the last line: `printR` uses the R API printing function to print an R object. If you pass a string as the argument to `printR`, it will print the object with that name in R. It will *not* print the string that you pass to it as an argument. D does not know anything about `m`. It only knows about `dm`, which holds a pointer to `m`.\n\n# RVector\n\nA vector can be represented as a matrix with one column. In R, vectors and matrices are entirely different objects. That doesn't matter much in D because vectors *are* represented as matrices in D. I have added an `RVector` struct to allow the use of `foreach`. Here is an example:\n\n```\nimport embedr.r;\nimport std.stdio;\n\nvoid main() {\n  // Have R allocate a vector with 5 elements and copy the elements of the double[] into it\n\tauto v = RVector([1.1, 2.2, 3.3, 4.4, 5.5]);\n  \n  // Pass v to R, creating variable rv inside the R interpreter\n\tv.toR(\"rv\");\n\tprintR(\"rv\");\n\t\n  // Use foreach to print the elements\n\tforeach(val; v) {\n\t\twriteln(val);\n\t}\n}\n```\n\n# RVector Slices\n\nYou can slice an RVector, as shown in this example.\n\n```\nimport embedr.r;\nimport std.stdio;\n\nvoid main() {\n\tevalRQ(`v \u003c- rnorm(15)`);\n\tauto rv = RVector(\"v\");\n\tforeach(val; rv) {\n\t\twriteln(val);\n\t}\n\trv[1..5].print(\"This is a slice of the vector\");\n}\n```\n\n# Working With R Lists\n\nLists are very important in R, as they are the most common way to construct a heterogeneous vector. Although you could work directly with an R list (there's an `RList` struct to do that) you lose most of the nice features if you do. For that reason I created the `NamedList` struct. You can refer to elements by number (elements are ordered as in any array) or by name. You can add elements by name (but only that way, because every element in a `NamedList` needs a name).\n\n```\n\nimport embedr.r;\nimport std.stdio;\n\nvoid main() {\n  // Create a list in R\n  evalRQ(`rl \u003c- list(a=rnorm(15), b=matrix(rnorm(100), ncol=4))`);\n  \n  // Create a NamedList struct to work with it in D\n  auto dl = NamedList(\"rl\");\n  dl.print;\n  \n  // Pull out a matrix\n  auto dlm = RMatrix(dl[\"b\"]);\n  dlm.print(\"This is the matrix from that list\");\n  \n  // Pull out a vector\n  auto dlv = RVector(dl[\"a\"]);\n  dlv.print(\"This is the vector from that list\");\n\n  // Create a NamedList in D and put some R objects into it\n  // NamedList holds pointers to R objects, which can be pulled\n  // out using .data\n  NamedList nl;\n  nl[\"a\"] = dlm.data;\n  nl[\"b\"] = dlv.data;\n  \n  // Send to R as rl2\n  nl.toR(\"rl2\");\n\t\n  // Can verify that the elements are reversed\n  printR(\"rl2\");\n}\n```\n\n# Scalars and Strings\n\nR does not have a scalar type. What appears to be a scalar is a vector with one element. On the D side, however, there are scalars, so you have to specify that you are working with a scalar your D code. On a different note, we can pass strings between R and D.\n\n```\nimport embedr.r;\nimport std.stdio;\n\nvoid main() {\n  // Create some \"scalars\" in R\n  evalRQ(`a \u003c- 4L`);\n  evalRQ(`b \u003c- 4.5`);\n  evalRQ(`d \u003c- \"hello world\"`);\n\t\n  // Print the values of those R variables from D\n  // Pull the integer a from R into D\n  writeln(scalar!int(\"a\"));\n  \n  // Also pulls in an integer, but creates a long rather than int\n  writeln(scalar!long(\"a\"));\n  \n  // The default type of scalar is double, so it is not necessary to specify the type in that case\n  writeln(scalar(\"b\"));\n  \n  // Pull the string d from R into D\n  writeln(scalar!string(\"d\"));\n\t\n  // Can also work with a string[]\n  [\"foo\", \"bar\", \"baz\"].toR(\"dstring\");\n  printR(\"dstring\");\n\t\n  // Create a vector of strings in R and pull it into D as a string[]\n  evalRQ(`rstring \u003c- c(\"under\", \"the\", \"bridge\")`);\n  writeln(stringArray(\"rstring\"));\n}\n```\n\nThere is more functionality available (the entire R API, in fact) but the single goal of this library is to facilitate the passing of commonly-used data types between the two languages. Other libraries are available for the functions in the R standalone math library, optimization, and so on.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbdilday%2Fembedr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbdilday%2Fembedr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbdilday%2Fembedr/lists"}