A tale of C++ native Ruby and RAII

While I was playing with my last project, I wanted to gather the execution time of a few native functions. Doing so in C is a little bit painful: it requires quite a bit of code, temporary variable, and such. One really powerful idiom I liked using while doing C++ was Resource Acquisition Is Initialization (RAII) to do this kind of task. This post will contain two subjects: using RAII to time function execution and using rake-compiler with C++ for native Ruby. So here is a tale of C++ native Ruby and RAII.

What is RAII

In a class, RAII is represented in a really simple way: the constructor acquires something (file handle, lock, etc.) and the destructor releases it.

An example of this is the std::ofstream class. An instance of this class acquires a handle on the given file and the destructor releases it. Therefore, the following is completely valid:

This idiom ensures that the underlying resource gets released correctly in all cases. No need to catch exceptions and rethrow in order to manually close the file, it will be done when the stack unwinds.

Using RAII to time function execution

In order to use RAII to time function execution, I went with a really simple flow:

  • The constructor gets the start time
  • The destructor gets the end time and prints the elapsed time

The code using the previous flow can be found here:

Using this class becomes super simple: create an instance and let it go out of scope. An example of this can be found in this file:

Using rake-compiler with C++

I was expecting some major differences when using C++ instead of C with rake-compiler. Turns out that the tool does most of the heavy lifting. I only needed to put the C++ files in the directory and they got built magically.

There were only a few things that I needed to care about:

  • Ensure that the entrypoints were in an Extern C section in order for the method signatures to be valid
  • Define a typedef to enforce C signatures whenever you call a C Ruby function that requires a function pointer
  • In order to manage memory correctly, remember to delete any allocated instances

Using rake-compiler to build native Ruby extensions

Having renewed my love for my Raspberry Pi, I wanted to make a quick library to access a temperature sensor through Ruby. This sensor uses a single-bus format, and one communication lasts about 4ms. I felt like this was good enough of an excuse to play with the native layer of Ruby. Here is how I ended up using rake-compiler to build native Ruby extensions.

Quick disclaimer: most of what I did was heavily inspired by a RubyGems guide. I’ll try to point out things that I had most issues with or that I found particularly interesting. All the code associated with this post is hosted on my GitHub project.

Adding a dependency on an external library

Adding a dependency on an external library was one of the things that were not completely clear. In my case, I needed to use libgpiod. In order to do so, I had to modify extconf.rb to add the following lines:

These two lines ensure that the generated Makefile will include the right search directories for the headers and link to the right library.

Controlling the native classes’ modules

I ended up with a really simple solution for handling my modules: the module is created in Ruby, and then fetched in C and used there. In the sample project, the module creation is done in the main Ruby file and then used when initializing the C module.

Getting the module was done easily: rb_const_get(rb_cObject, rb_intern("NCI")). Once this was done, creating the class was done using the handy rb_define_class_underrb_define_class_under(mNCI, "NCINativeDevice", rb_cObject). The third parameter to this last function is the superclass, in this case the Object class.

Associating a C structure with the Ruby instance

Three functions come into play when using a C structure: nci_native_device_allocnci_native_device_init, and nci_native_device_free.

The first function (_alloc) is used to allocate an empty C structure. This function is not the initializer, it will not get any of the arguments passed on initialization. The important part of the function is the call to Data_Make_Struct. This function will allocate the given C structure, but won’t initialize it for you.

The second function (_init) is the true initializer. It will receive the arguments that are passed in the Ruby code. In order to store these values in the C structure, you need to extract the C pointer from the instance. This is done using Data_Get_Struct. Weirdly enough, this won’t return the pointer to the C structure, it stores it in the last argument.

The last function (_free) is the most important of all. It is responsible for deallocating whatever you allocated. The C structure (allocated for you by Data_Make_Struct) does not need to be deallocated, the system will do it for you.

Various sources

Custom initializer when subclassing Dry::Struct

I’ve been using dry-struct in most of my Ruby projects. This time around, I had to do something a little bit unusual: I have a subclass that requires less information than its parent. So here is how I wrote my custom initializer when subclassing Dry::Struct.

The Problem

The solution seems simple: the subclass should simply not send part of the information to its base constructor. But Dry::Struct was built in a way that we can’t do that as easily. The first thing I tried was the following:

Line 21 works correctly, but this is not what I wanted to achieve. I wanted to not have to specify X when creating the object, like the line 22. When doing so, I got greeted with a: in `block in resolve_missing_keys': :X is missing in Hash input (Dry::Types::MissingKeyError).

After investigating the callstack, I figured that the validation was not done in the initializer, but in the class’s new function.

The Solution

Armed with the information that the validation is done in the new function, I tried something else. The following is the version I ended up with:

The magic is on line 15: instead of defining an initializer, I overload the new function of my class. This allows me the same control as an initializer but does this before Dry::Struct validations.

Now, is this the best solution … probably not. But following the documentation, I could not find any other ways to do it.

Using SemanticLogger with Highline in Ruby

I started using Ruby again for a command-line project of mine. In order to do all that I needed to do, I had to find a configurable library for logging (kinda like log4net and friends) and another one to ask various input from the command line. Therefore, I ended up using SemanticLogger with Highline. I ended up having a few issues, here is how I fixed them.

The problem

The first input I did, after showing a few debug information, ended up a mangled mess looking like:

You can clearly see that the output is intertwined with the input selection. This is really annoying and needed fixing.

The associated code did not look anything weird, even a simple test like the following produces the issue:

The only explanation for me was that the output from the logger was done in an asynchronous way, either some kind of buffering or simply done in a background thread. After checking a bit more  Highline’s homepage, I found the answer:

Logging is performed in a separate thread so as not to slow down the application whilst logging to one or more destinations.

The solution

After looking through more guides from the official site, I finally found what I needed: a way to make SemanticLogger log in the current thread.

There are multiple ways of enabling this feature, I decided to go with the code-based approach: add  ::SemanticLogger.sync! before any of my appenders got created.

Doing so, my final solution looks like:

And my output is finally as expected:

Interacting with Google Tasks using Ruby

On the first iteration of a project of mine, I wanted to access Google Tasks using Ruby. Therefore, I did a little bit of tinkering with using the Google Tasks API using Ruby. In this post, I will go over your project’s setup, the Google backend setup and the basic usage of the API.

Project Setup

All of the Google Tasks APIs are basically REST endpoints. One could simply call all these HTTP endpoints manually, but this would be painful. I decided to use google-api-client to do all the heavy lifting. In order to include it in your project, simply add the following to your Gemfile:

Google API Setup

In order to access Google Tasks using Ruby, you will need to use Google’s OAuth. Google’s OAuth uses what they call client secrets file. These files contain all the information needed to access the selected services.

To get a client secrets file, you can follow my other post.

Handling the user’s credentials

The way the Google APIs work, an URL will be provided to you. Opening that URL and grabbing the authentication token is all on you. Therefore, there is three consideration when handling the user’s credential:

  1. Storing the credentials (so that you don’t ask access every time);
  2. Showing the consent webpage;
  3. Grabbing the authentication token;

For this quick test, I decided to use a file storage for the token. The FileTokenStore token store will simply use a YAML file to store the user’s tokens. To show the consent webpage, I went with launchy. This cross-platform library will handle opening URLs in the default browser and such. Finally, I decided to basically do nothing to grab the token: I expect the user to paste it on the command line.

Initializing the Google Tasks API

Now that you have the user’s credentials, you can initialize the API you want to use. In my case, this is the task API. In order to do so, simply create a new instance of the service you want to use (Google::Apis::TasksV1::TasksService) and set its authorization member to the credentials you got from the client.

Interacting with Google Tasks using Ruby

Creating a task list

The tasklist is basically a grouping of tasks. It is the root concept of Google Tasks. Creating one is quite straightforward:

Finding a task list

The Google Tasks API only allows you to search by tasklist ID, not a title. This ID is automatically generated and therefore not really easy to use. The easiest way to find a task list is to list all task lists and find the one you are looking for in there:

Creating a task

Creating a simple task, at the top of the task list is quite straightforward:

Finding a task

Just like finding a task list, finding a task by its title can’t be done directly through the API. In order to do so, you need to iterate over the tasks and check them:

Updating a task

Once you have your hand on the task you want to update, simply update the field you want to update and call update_task:

Completing a task

Completing a task is done by setting its status to “completed” and updating the task:

Handling a large number of return values

Google’s Task API uses pagination in order to handle a large number of return values. By default, a maximum of 100 return values will be returned by calls to list_tasklists and list_tasks. The return values of these two APIs will contain a next_page_token value. You can then use this token in a subsequent call to the API specifying the optional argument page_token in order to get another set of return values.

Here is a quick example of handling of pagination with the list_tasks call. Do note that in this example, I set the max_results value in the call so that I do not have to create 100+ tasks.