Forum: Ruby Multiple c extensions with the same function names

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ian C. (Guest)
on 2009-02-03 17:34
Hi,

A bit of a noob questions here, so please bear with me. I've been
attempting to use multiple C extensions containing identical c function
names. I had assumed  that because the functions were in different
modules (.so dynamic libraries) it would be unlikely for there to be any
name clashes. However, when creating new instances from these loaded
modules, there seems to be an issue with instances calling functions
belonging to other classes.

For example, assuming the source file TestA.c contains:

#include "ruby.h"
#include "malloc.h"


VALUE CTestA;


typedef struct _tba {
  int statusf;
  int request;
} TestAbox;


static void c_free(void *p) {
  TestAbox *data = (TestAbox*)p;
  free(data);
}


static VALUE
c_test(VALUE self)
{
  TestAbox *ptr;
  Data_Get_Struct(self, TestAbox, ptr);

  printf("TestA test function called\n");
  return Qnil;
}


static VALUE
c_init(VALUE self, VALUE unit)
{
  printf("TestA new init\n");
  return self;
}


VALUE c_new(VALUE class)
{
  printf("Creating new TestA instance\n");
  TestAbox *ptr = (TestAbox*)malloc(sizeof(TestAbox));
  VALUE tdata = Data_Wrap_Struct(class, 0, c_free, ptr);
  rb_obj_call_init(tdata, 0, NULL);
  printf("Successfully created TestA instance\n");
  return tdata;
}

With another TestB.c containing the same source but with any occurrence
of "TestA" having been replaced with "TestB"

Compiled against ruby 1.8.4 (2005-12-24) [x86_64-linux], using gcc
-shared to produce two .so files, TestA.so and TestB.so.

Then within irb:

irb(main):001:0> require 'testa/TestA'
Initialising TestA
TestA initialised
=> true
irb(main):002:0> require 'testb/TestB'
Initialising TestB
TestB initialised
=> true
irb(main):003:0> testa=TestA.new()
Creating new TestA instance
TestA new init
Successfully created TestA instance
=> #<TestA:0x2ab3676822e0>
irb(main):004:0> testb=TestB.new()
Creating new TestA instance
TestB new init
Successfully created TestA instance
=> #<TestB:0x2ab367676850>
irb(main):005:0>

I would be very grateful if someone could explain what was happening
here. My guess would be memory addresses being overwritten for symbols
with the same name when modules are loaded in. It would just be nice to
know that it's not something more sinister that I am doing incorrectly.
So if this is not how  Ruby C extensions should be used, is the answer
to use unique names between modules? This just seems a little odd to me.

Many thanks.
Nobuyoshi N. (Guest)
on 2009-02-03 17:59
(Received via mailing list)
Hi,

At Wed, 4 Feb 2009 00:33:40 +0900,
Ian Campbell wrote in [ruby-talk:326749]:
> I would be very grateful if someone could explain what was happening
> here. My guess would be memory addresses being overwritten for symbols
> with the same name when modules are loaded in. It would just be nice to
> know that it's not something more sinister that I am doing incorrectly.

Ruby uses RTLD_GLOBAL flag to dlopen() on Linux, but it can
vary on other platforms.  You can't depend on whether a symbols
in an extension library is visible from another extension
library.

> So if this is not how  Ruby C extensions should be used, is the answer
> to use unique names between modules? This just seems a little odd to me.

Making them static except for Init function.
Ian C. (Guest)
on 2009-02-04 12:08
Hi Nobuyoshi,

Many thanks for your explanation; the use of dlopen() with RTLD_GLOBAL
makes perfect sense.

Full steam ahead now!
This topic is locked and can not be replied to.