Debugging Ruby C Extension gem - ruby

I've been trying to debug ruby gem made with Ruby C Extension to figure out how it works, so I can modify it to my own use. It's quite an advanced gem and printing values isn't enough. So I started debugging it with gdb and gdb-ruby gem. I created instance of class in ruby and ran a method that later connects to functions written in C. There was no way I could stop at certain line in C function even after placing breakpoint. To debug ruby I use 'pry' gem if that means anything. Is there a straightforward way to place a breakpoint inside C function, so it stops at it when reaching given function/line in C file after running Ruby program?

Related

What exactly is a gem native extension?

I feel that a native extension is like libraries that you should install onto your system before trying to install those gems, which depend on the native extensions. Like the ImageMagic library. Is that correct? Is there something else that we should know about native extensions?
A gem native extension might link to a separate library that needs to be pre-installed, and RMagick is an example of that.
However, the term really just means "includes some code that needs to be compiled for your machine". The code is compiled and linked so that the resulting executable file can be required by Ruby on the machine.
The usual reasons for writing a Ruby C or C++ extension are:
Speed. For some CPU-intense tasks, C code can be 100 times faster than Ruby. In this case a native extension can be completely stand-alone with all C source code included in the gem.
Third-party library already written in C. In this case the gem will have C source code that binds the library functions into Ruby modules, classes and methods.
You can view the C source code for gems with native extensions, it is installed alongside the Ruby source code. By convention, there is a folder inside the gem called ext/gem_name which contains a Ruby file extconf.rb that passes information to the compiler (technically it creates a make file). In addition the C source files are put there as well.
MRI Ruby is implemented as a very "flat" structure in C, basically consisting of a large number of C functions. This makes it relatively easy to learn how to implement a native extension, even if you don't know much C. You can read Extending Ruby 1.9 as an introduction to the topic.
Native extensions can fail to install or work properly. There are many questions on Stack Overflow asking for help with specific failed installs. The usual problems are:
Missing libraries. Hopefully the gem author will explain what you need to pre-install in the README, but is not always clear.
Compiler mismatches. It is difficult to test all target systems, so sometimes the instructions in extconf.rb won't work on a specific system, or the C code will raise warnings or not compile due to differences. In Windows, you probably won't have a working compiler unless you install the Ruby Devkit
Will not work with all versions of Ruby. For instance, JRuby can use C native extensions, if it has been enabled but it is not always advisable - the topic is quite complex, but generally avoid mixing JRuby and native extensions.
Native extension is just a gem which is written (entirely or partially) in C.
It may or may not depend on an external library, this is not a factor here. What matters is that such gem needs to be compiled and it is likely to be platform-dependant (there was a reason to use C, right? Maybe for using some low-level OS API or something. But most often it's to interface with a library).
Quoting this article
“Native extensions” are the glue that connects a Ruby gem with some other non-Ruby software component or library present on your machine.
The native extensionis not the dependency. A native extension is generally a C code that interacts with a non-Ruby dependency.
For instance, a gem that uses ImageMagic have a native extension written in C that talks to ImageMagic and represents the bridge from the Ruby gem to ImageMagic.
When you install the gem and the native extension is compiled, you don't compile the C library (e.g ImageMagic), that library must be already present on your system. You compile the C bridge bundled with the gem.
I'm not big ruby specialist, so take this with a grain of salt:
I'm fairly certain that it's just a gem that needs to install a native (e.g. C-Library) library in order to work. A lot of gems simply wrap existing C-libraries with a Ruby API.
The installation of the gem will trigger the download of C-libraries, which will then be built using gcc or another compiler. If your system configuration is not supported, you'll need to pass parameters to gem tool to indicate the right directories, etc.. if you're unlucky you might need to change the make files directly.

Fetching a URL without C Extensions/Libraries

I'm working within the context of RPG Maker VX Ace. It has some Ruby extensions, and it has a subset of the Ruby 1.8 library built in. It also allows me to add my own .rb files -- such as the Ruby 1.9.3 source files -- albeit that I cannot use any code that has C extensions. If it requires a .so file, it won't work -- I'll get an error that "this application cannot load extensions/plugins."
Having understood this, I need some way to make an HTTP request. What I mean is:
Call a URL (eg. http://myserver.com/blah?data=abcd
Return the response (which will be a string -- not full HTML, just an identifier of some sort)
I have tried using open-uri and net/http. Both of them have different issues that prevent me from using. One (I think it's the latter) requires TcpSocket, which is implemented in C and is not "pure" Ruby. The other one gives me an error about an undefined constant related to sockets.
I've also tried using the Socket class, and it gives me a similar error.
TLDR: Is there some way I can make a Ruby HTTP call with pure Ruby, no C extensions? That is what I need.
I solved this by writing some code and calling it from Ruby. Easy breezy.
Using .NET, I created a non-command-line, non-service application; something which I can invoke like a command-line app, but without the command-line window. To do this:
Create a new command-line project
Go to project properties
Change the type to "Windows Forms Application"
When you run your project, it'll run like any command-line project (args, etc.) but no windows will appear.
From there, it was easy to make an asynchronous HTTP request and store the response in a text file. This is sufficient for now.
You could call out to a shell and execute curl (depending on your environment and the speed you want)
result = `curl "http://myserver.com/blah?data=abcd" -s`
The -s makes curl silent. See if that stops the dos box coming up.

Ruby wrapper over a existing C library

I want write a ruby wrapper for a existing C library (.so files). Can anyone point me to books/websites that can get me started with this.
You have several options:
swig / hand written C
extension but those won't be
usable in other VM than MRI (won't
work in jruby, rubinius...)
FFI which will be usable on
other VM. example here
Take a look at FFI gem.

How do I compile irb from source on Ubuntu?

I would like to compile irb from source without any optimizations so I can get more information while stepping through (interpreter) code using gdb. I have successfully compiled ruby 1.9.1 without problems, but I cannot find any documentation regarding irb. I believe that irb is included in the ruby 1.9 source, but have not been able to verify this. Can anyone point me in the right direction?
Can you clarify what you mean exactly by "compiling IRb without optimizations"?
You don't say which implementation of Ruby you are using. I am going to assume you are using YARV.
With, YARV, there is no separate compile step, it compiles IRb automatically for you, everytime you run it. (Even though YARV is a compiler, you can think of it as an interpreter, since you never have to worry about the compilation step.) Also, YARV doesn't do any optimizations when compiling AFAIK, and if it does, there is no way to influence the compilation, thus also no way to turn optimizations off.
IRb is quite easy to find in the YARV sourcecode. The executable lives in the bin directory:
bin/irb
But it's not doing any interesting work. The real meat is in the standard library:
lib/irb.rb and
the whole lib/irb/ directory

(Ruby) Compiling dynamic applications for Windows?

Does anyone have any insights regarding compiling Ruby code for Windows? I've tried both "Ruby2Exe" and "OCRA", but both present their own issues. Ruby2Exe keeps presenting vague or confusing warnings such as "can't modify frozen string". OCRA on the other hand seems to want to run your script and assumes that there are no dynamic items.
For the record, my script accepts command line arguments as well as reading in and parsing a text file. OCRA doesn't like this aspect at all, and actually throws the warnings in my code as if I tried to run the script.
Anyway, if anyone has any quality means by which to compile ruby code for Windows, I'm all ears.
As a bit of an FYI, my goal with this particular script is to send email over SMTP. It is part of a larger non-ruby application, but the framework is incapable of sending email. I find Ruby enjoyable and rather easy to work with but don't wish to have every end user install Ruby -- hence, the need/desire to "compile" it.
I'm on a short time table and can't really afford to expend resources on writing this in C++, etc. However, if anyone has any insights on any existing Windows-compatible libaries/applications, do tell.
Much appreciated.
"OCRA on the other hand seems to want to run your script..."
The constant Ocra is defined at compile-time but not at run-time. So you can include logic based on whether or not the Ocra constant is defined. For example:
app = MyApp.new
if not defined?(Ocra)
app.main_loop
end

Resources