Writing extensions for Ruby is easy, far easier than for most dynamic languages. Ruby handles the garbage collection and doesn't require the user know too much about how memory is managed. However, there are some easy pitfalls and common problems that the programmer can run into. Security. C code should always check the safe level to ensure that unsafe operations are disallowed. Taint checks should be done to ensure tainted data is not blindly trusted. Exception safety. It is imperative that C++ exceptions never make their way into C code, and it is also important that a Ruby exception not bypass resource cleanup in C or C++ code. Rules for when it is okay to use which exceptions are difficult to get right, especially as code is maintained through time. Thread safety. Because the Ruby interpreter is not thread-safe, the Ruby interpreter must not be run from more than one thread. It's not enough to ensure that only one thread runs the interpreter at any given time; once the interpreter has been run from one thread, it must only ever be run from that thread in the future. Additionally, code must be careful not to access objects in one Ruby thread that were created on the stack in another thread. GC safety. Too keep an object alive, it must be marked during the mark phase. Object references on the heap should be registered with rb_gc_register_address or marked by a mark function; object references on the stack will be automatically marked, provided the Ruby interpreter was properly initialized at startup. Unit testing. Because the extension usually interfaces directly with an API that wasn't designed for testing, mock objects are sometimes not a trivial option. Unit testing extensions is very necessary but not very easy. Inheritance. When wrapping objects, a convention must be chosen whether to store a pointer to the base type or the derived type. In either case, there will likely be some conversion necessary when the object is unwrapped. A system that properly handles inheritance for all corner cases is nontrivial. Additionally, C++ supports multiple inheritance, but the Ruby object model uses single inheritance with mixins. When wrapping a library that uses multiple inheritance, care must be taken in constructing the mapping. Callbacks. C implements callbacks via function pointers, while ruby typically implements callbacks via procs. Writing an adapter function to call the proc is not difficult, but there is much opportunity for error. Data serialization. By default data objects defined at the C layer are not marshalable. The user must explicitly define functions to marshal the data member-by-member. API conversion. It is not common for a C API to map cleanly onto a Ruby API. More often than not, an exact mapping of the API makes for an API that is not very friendly. However, an idiomatic mapping of an API creates a challenge for documenting the extension.