summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2015-04-06 12:22:11 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2015-04-06 12:24:04 -0700
commit9a536029c699ee501d9278577a300a5ef3d147dd (patch)
tree7e3d63890d70f72a048a64cd6f4e52c9075d99fa
parent10c7da3b6002a59e21c9c8ee202f6f713c3959f9 (diff)
downloadffi-yajl-9a536029c699ee501d9278577a300a5ef3d147dd.tar.gz
add native dlopen extension code
This will get dlopen in a consistent place on all the platforms which need it.
-rw-r--r--Rakefile7
-rw-r--r--ext/ffi_yajl/ext/dlopen/dlopen.c38
-rw-r--r--ext/ffi_yajl/ext/dlopen/extconf.rb15
-rw-r--r--ffi-yajl.gemspec3
-rw-r--r--lib/ffi_yajl.rb8
-rw-r--r--lib/ffi_yajl/ext.rb51
6 files changed, 69 insertions, 53 deletions
diff --git a/Rakefile b/Rakefile
index d8926dc..ae19344 100644
--- a/Rakefile
+++ b/Rakefile
@@ -51,6 +51,13 @@ Rake::ExtensionTask.new do |ext|
ext.gem_spec = spec
end
+Rake::ExtensionTask.new do |ext|
+ ext.name = 'dlopen'
+ ext.lib_dir = 'lib/ffi_yajl/ext'
+ ext.ext_dir = 'ext/ffi_yajl/ext/dlopen'
+ ext.gem_spec = spec
+end
+
#
# test tasks
#
diff --git a/ext/ffi_yajl/ext/dlopen/dlopen.c b/ext/ffi_yajl/ext/dlopen/dlopen.c
new file mode 100644
index 0000000..7330763
--- /dev/null
+++ b/ext/ffi_yajl/ext/dlopen/dlopen.c
@@ -0,0 +1,38 @@
+#include <ruby.h>
+
+#if defined(HAVE_DLFCN_H)
+# include <dlfcn.h>
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 0
+#endif
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+#ifndef RTLD_NOW
+#define RTLD_NOW 0
+#endif
+#else
+# if defined(_WIN32)
+# include <windows.h>
+# define dlopen(name,flag) ((void*)LoadLibrary(name))
+# define dlerror() strerror(rb_w32_map_errno(GetLastError()))
+# define dlsym(handle,name) ((void*)GetProcAddress((handle),(name)))
+# define RTLD_LAZY -1
+# define RTLD_NOW -1
+# define RTLD_GLOBAL -1
+# endif
+#endif
+
+static VALUE mFFI_Yajl, mDlopen, mExt;
+
+static VALUE mDlopen_dlopen(VALUE self, VALUE file) {
+ dlopen(RSTRING_PTR(file), RTLD_NOW|RTLD_GLOBAL);
+ return Qnil;
+}
+
+void Init_dlopen() {
+ mFFI_Yajl = rb_define_module("FFI_Yajl");
+ mExt = rb_define_module_under(mFFI_Yajl, "Ext");
+ mDlopen = rb_define_module_under(mExt, "Dlopen");
+ rb_define_method(mDlopen, "dlopen", mDlopen_dlopen, 1);
+}
diff --git a/ext/ffi_yajl/ext/dlopen/extconf.rb b/ext/ffi_yajl/ext/dlopen/extconf.rb
new file mode 100644
index 0000000..7e18469
--- /dev/null
+++ b/ext/ffi_yajl/ext/dlopen/extconf.rb
@@ -0,0 +1,15 @@
+require 'mkmf'
+require 'rubygems'
+
+RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
+
+puts $CFLAGS
+puts $LDFLAGS
+
+have_header("dlfcn.h")
+
+have_library("dl", "dlopen")
+
+dir_config 'dlopen'
+
+create_makefile 'ffi_yajl/ext/dlopen'
diff --git a/ffi-yajl.gemspec b/ffi-yajl.gemspec
index 8e6943d..2801527 100644
--- a/ffi-yajl.gemspec
+++ b/ffi-yajl.gemspec
@@ -1,7 +1,6 @@
gemspec = eval(IO.read(File.expand_path(File.join(File.dirname(__FILE__), "ffi-yajl.gemspec.shared"))))
gemspec.platform = Gem::Platform::RUBY
-gemspec.extensions = %w{ ext/ffi_yajl/ext/encoder/extconf.rb ext/ffi_yajl/ext/parser/extconf.rb }
+gemspec.extensions = %w{ ext/ffi_yajl/ext/encoder/extconf.rb ext/ffi_yajl/ext/parser/extconf.rb ext/ffi_yajl/ext/dlopen/extconf.rb }
gemspec
-
diff --git a/lib/ffi_yajl.rb b/lib/ffi_yajl.rb
index 7f39189..1787766 100644
--- a/lib/ffi_yajl.rb
+++ b/lib/ffi_yajl.rb
@@ -19,10 +19,10 @@ elsif ENV['FORCE_FFI_YAJL'] == "ffi"
require 'ffi_yajl/ffi'
elsif RUBY_PLATFORM == "java"
require 'ffi_yajl/ffi'
-elsif defined?(Yajl)
- warn "the ffi-yajl and yajl-ruby gems have incompatible C libyajl libs and should not be loaded in the same Ruby VM"
- warn "falling back to ffi which might work (or might not, no promises)"
- require 'ffi_yajl/ffi'
+#elsif defined?(Yajl)
+# warn "the ffi-yajl and yajl-ruby gems have incompatible C libyajl libs and should not be loaded in the same Ruby VM"
+# warn "falling back to ffi which might work (or might not, no promises)"
+# require 'ffi_yajl/ffi'
else
begin
require 'ffi_yajl/ext'
diff --git a/lib/ffi_yajl/ext.rb b/lib/ffi_yajl/ext.rb
index bc4d410..12f74d9 100644
--- a/lib/ffi_yajl/ext.rb
+++ b/lib/ffi_yajl/ext.rb
@@ -4,60 +4,17 @@ require 'ffi_yajl/encoder'
require 'ffi_yajl/parser'
require 'libyajl2'
require 'ffi_yajl/map_library_name'
+require 'ffi_yajl/ext/dlopen'
module FFI_Yajl
extend FFI_Yajl::MapLibraryName
+ extend FFI_Yajl::Ext::Dlopen
+
libname = map_library_name
libpath = File.expand_path(File.join(Libyajl2.opt_path, libname))
- #
- # FFS, what exactly was so wrong with DL.dlopen that ruby had to get rid of it???
- #
-
- def self.try_fiddle_dlopen(libpath)
- require 'fiddle'
- if defined?(Fiddle) && Fiddle.respond_to?(:dlopen)
- ::Fiddle.dlopen(libpath)
- true
- else
- false
- end
- rescue LoadError
- return false
- end
-
- def self.try_dl_dlopen(libpath)
- require 'dl'
- if defined?(DL) && DL.respond_to?(:dlopen)
- ::DL.dlopen(libpath)
- true
- else
- false
- end
- rescue LoadError
- return false
- end
-
- def self.try_ffi_dlopen(libpath)
- require 'ffi'
- require 'rbconfig'
- extend ::FFI::Library
- ffi_lib 'dl'
- attach_function 'dlopen', :dlopen, [:string, :int], :void
- if RbConfig::CONFIG['host_os'] =~ /linux/i
- dlopen libpath, 0x102 # linux: RTLD_GLOBAL | RTLD_NOW
- else
- dlopen libpath, 0
- end
- true
- rescue LoadError
- return false
- end
-
- unless try_fiddle_dlopen(libpath) || try_dl_dlopen(libpath) || try_ffi_dlopen(libpath)
- raise "cannot find dlopen via Fiddle, DL or FFI, what am I supposed to do?"
- end
+ dlopen(libpath)
class Parser
require 'ffi_yajl/ext/parser'