Calling D Functions from R on Windows

This is a short tutorial explaining the steps needed to create a DLL with D that can be called from R. There is definitely more overhead getting set up on Windows than there is on Linux or Mac.

Note that you only need to torture yourself this way if you plan to compile the D functions on Windows. If you’re planning to call D functions that have been compiled by someone else, you don’t need to do any of this.

On the plus side, writing your functions in D is probably easier than writing them in C, because you don’t need to mess around with Rtools. That can be a frustrating experience.

This guide is specific to Windows. I plan to publish similar posts for Linux and Mac in the future. I wrote the Windows tutorial first because I had so much trouble figuring out how to do on Windows that which is really easy on Linux and Mac.

Installation

The first thing you need is the D compiler. The only D compiler that creates Windows .dll files is LDC. You can get it here. As of this writing (September 2017) the most recent release is 1.4.0, which you can download at this link.

LDC is distributed as a zip archive on Windows, so you don’t install it, you unzip it somewhere on your computer. I used C:\Users\lance. I will assume you did the same, though that is unlikely to be exactly correct unless you are also named Lance or regularly impersonate someone with that name.

The program you need to do the compilation is ldmd.exe. On my computer it is in the directory C:\Users\lance\prog\ldc2-1.4.0-win64-msvc\bin.

LDC requires Visual Studio for linking. You can download the Community Edition here. When you install, be sure you also install the C++ development tools. That’s a massive download, but in my experience, it’s the only option that works every time. You can install the smaller Visual C++ Build Tools but sometimes LDC has not worked properly when I’ve done that, so I just go with the bigger download.

The next thing you’ll need is an installation of R. As of this writing (September 2017) the current release is R 3.4.1. That will be installed by default in C:\Program Files\R, so I will assume that’s what you’ve done.

Preparing R.lib

Most useful D functions need to interact directly with R. That means you will need to call the functions in R.dll. On Windows, you need to create an import library, as you cannot simply call the functions as you do on Linux or Mac.

The easiest solution I have found to create an import library is to use pexports.exe provided by mingw. I downloaded mingw-get-setup.exe from here. I ran that and installed the three files labeled “mingw32-pexports”. I went with the default location C:\MinGW.

I created a directory to test this out called C:\Users\lance\embedr and copied R.dll into that directory. Then at the command prompt (for some reason it does not work in Powershell on my machine) I ran the following:

cd C:\Users\lance\embedr
"C:\MinGW\bin\pexports.exe" R.dll > R.def
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\bin\HostX64\x64\lib.exe" /def:R.def /out
:R.lib /machine:x64

Creating a DLL

Put the following in a file titled librtest.d inside the same directory that holds R.lib:

import embedr.r;
mixin(createRLibrary("rtest"));

import std.math;

export extern(C) {
  Robj transform(Robj rx) {
    auto x = RVector(rx);
    double[] y = [log(x[0]), log(x[1])];
    double result = y[0] + y[1];
    return result.robj;
  }
}

Download r.d at this link. Save it inside the same directory as librtest.d. Now create the DLL. At the command prompt inside the embedr directory:

"C:\Users\lance\prog\ldc2-1.4.0-win64-msvc\bin\ldmd2.exe" -shared -m64 librtest.d r.d -version=inline R.lib

If everything above has been done correctly, you should have a file called librtest.dll in the embedr directory.

Call the D function

Open the 64-bit installation of R (you have both a 32-bit and 64-bit installation). Navigate to the embedr directory, load the DLL, and call it:

setwd("C:/Users/lance/embedr")
dyn.load("librtest.dll")
.Call("transform", c(2.0, 3.0))

You should get the output:

[1] 1.791759

If that worked, you can now write and call arbitrary D functions from R on Windows.


⤺ Back to the List of Computing Posts