julia 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ffe6273a8591b918cc6e38e68d6f3301e2b14bee
4
- data.tar.gz: 790bd12e87a137f6b57e7926517da57bde91c552
2
+ SHA256:
3
+ metadata.gz: 761658bd92a75b136265135887ffe7ca82a3c42d7e5d15ea5f6f9d8212d23ec1
4
+ data.tar.gz: 0052f5ad9249ff2063eceae0919573fea27039611824cad251b5aa63bdef57e1
5
5
  SHA512:
6
- metadata.gz: e3f48e6edcb0d0ee8d15d4775fd61dcc046824af9d8b6df0f81ed035f84785d70c33371d0ead89ae63f96ce0088602002a287b03dc8e040839304e4103195651
7
- data.tar.gz: 4d0a8208bda0274b58610bc40cf11d937561e471679fbe4bcb7f991e917c51670d772fff62fb889ff5951482e1989a19f70c091311e69fc5b7cbc584a6e2d3a7
6
+ metadata.gz: d6cf4724a9648c91ec03ed60fc1e9f3a337adc11ba1320ac74fedb7a0b6d12bde7fe1f050e9ca4e1d594caf45991977ee8f68ed6620d5beeb9fae79f6ca04c5b
7
+ data.tar.gz: 01d84c23f8c58efa7bd41a241389195e50a6842a6bd0ba0ae7fae77abb5b04bcb135d022b8cfe6a6372b5d4bcfbf18c8a3dd0b4f13f385057e898667c014b120
data/README.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  Julia on Ruby.
4
4
 
5
+ ## Supported versions
6
+
7
+ ### Ruby
8
+
9
+ - 2.5
10
+ - 2.4
11
+ - 2.3
12
+
13
+ ### Julia
14
+
15
+ - 1.0
16
+ - 0.7
17
+ - 0.6
18
+
5
19
  ## Installation
6
20
 
7
21
  Add this line to your application's Gemfile:
@@ -23,14 +37,17 @@ Or install it yourself as:
23
37
  ```ruby
24
38
  require 'julia'
25
39
 
26
- Julia.init(ENV['JULIA_HOME'])
27
- Julia.eval_string('print(pi)')
40
+ Julia.eval('print(pi)')
28
41
  ```
29
42
 
30
43
  ## Contributing
31
44
 
32
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/julia.
45
+ Bug reports and pull requests are welcome on GitHub at https://github.com/mrkn/julia.
46
+
47
+ ## Authors
33
48
 
49
+ - Kenta Murata
50
+ - Kenta Tanoue
34
51
 
35
52
  ## License
36
53
 
data/Rakefile CHANGED
@@ -1,6 +1,11 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "rake"
3
5
  require "rake/extensiontask"
6
+ require "rspec/core/rake_task"
7
+
8
+ Dir[File.expand_path('../tasks/**/*.rake', __FILE__)].each {|f| load f }
4
9
 
5
10
  Rake::ExtensionTask.new('julia')
6
11
 
@@ -6,9 +6,5 @@ require "julia"
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start
9
+ require "pry"
10
+ Pry.start
@@ -1,8 +1,3 @@
1
1
  require 'mkmf'
2
2
 
3
- dir_config('julia')
4
- have_header('julia.h')
5
- have_library('julia')
6
- have_func('jl_init')
7
-
8
- create_makefile('julia')
3
+ create_makefile('julia')
@@ -1,30 +1,19 @@
1
- #include <julia.h>
2
- #include <ruby.h>
1
+ #include "julia_internal.h"
3
2
 
4
- VALUE rbjl_mJulia;
3
+ VALUE julia_mJulia;
5
4
 
6
- static VALUE
7
- rbjl_julia_s_init(VALUE mod, VALUE home)
5
+ static void
6
+ init_julia(void)
8
7
  {
9
- SafeStringValue(home);
10
- jl_init(NIL_P(home) ? NULL : StringValueCStr(home));
11
- return mod;
12
- }
13
-
14
- static VALUE
15
- rbjl_julia_s_eval_string(VALUE mod, VALUE str)
16
- {
17
- SafeStringValue(str);
18
- jl_eval_string(StringValueCStr(str));
19
-
20
- return mod;
8
+ JULIA_API(jl_init)();
21
9
  }
22
10
 
23
11
  void
24
12
  Init_julia(void)
25
13
  {
26
- rbjl_mJulia = rb_define_module("Julia");
14
+ julia_mJulia = rb_define_module("Julia");
15
+
16
+ julia_init_libjulia();
27
17
 
28
- rb_define_module_function(rbjl_mJulia, "init", rbjl_julia_s_init, 1);
29
- rb_define_module_function(rbjl_mJulia, "eval_string", rbjl_julia_s_eval_string, 1);
18
+ init_julia();
30
19
  }
@@ -0,0 +1,125 @@
1
+ #ifndef JULIA_INTERNAL_H
2
+ #define JULIA_INTERNAL_H 1
3
+ #define JL_DATA_TYPE
4
+
5
+ #ifdef __cplusplus
6
+ extern "C" {
7
+ #if 0
8
+ } /* satisfy cc-mode */
9
+ #endif
10
+ #endif
11
+
12
+ #include <ruby.h>
13
+
14
+ #if SIZEOF_LONG == SIZEOF_VOIDP
15
+ # define PTR2NUM(x) (LONG2NUM((long)(x)))
16
+ # define NUM2PTR(x) ((void*)(NUM2ULONG(x)))
17
+ #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
18
+ # define PTR2NUM(x) (LL2NUM((LONG_LONG)(x)))
19
+ # define NUM2PTR(x) ((void*)(NUM2ULL(x)))
20
+ #else
21
+ # error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----
22
+ #endif
23
+
24
+ typedef struct _jl_value_t jl_value_t;
25
+ typedef struct _jl_taggedvalue_t jl_taggedvalue_t;
26
+
27
+ typedef struct _jl_sym_t {
28
+ JL_DATA_TYPE
29
+ struct _jl_sym_t *left;
30
+ struct _jl_sym_t *right;
31
+ uintptr_t hash;
32
+ } jl_sym_t;
33
+
34
+ typedef struct {
35
+ JL_DATA_TYPE
36
+ size_t length;
37
+ } jl_svec_t;
38
+
39
+ typedef struct {
40
+ uint32_t nfields;
41
+ uint32_t alignment : 9;
42
+ uint32_t haspadding : 1;
43
+ uint32_t npointers : 20;
44
+ uint32_t fielddesc_type : 2;
45
+ } jl_datatype_layout_t;
46
+
47
+ typedef struct {
48
+ JL_DATA_TYPE
49
+ jl_sym_t *name;
50
+ struct _jl_module_t *module;
51
+ jl_svec_t *names;
52
+ jl_value_t *wrapper;
53
+ jl_svec_t *cache;
54
+ jl_svec_t *linearcache;
55
+ intptr_t hash;
56
+ struct _jl_methtable_t *mt;
57
+ } jl_typename_t;
58
+
59
+ typedef struct _jl_datatype_t {
60
+ JL_DATA_TYPE
61
+ jl_typename_t *name;
62
+ struct _jl_datatype_t *super;
63
+ jl_svec_t *parameters;
64
+ jl_svec_t *types;
65
+ jl_svec_t *names;
66
+ jl_value_t *instance;
67
+ const jl_datatype_layout_t *layout;
68
+ int32_t size;
69
+ int32_t ninitialized;
70
+ uint32_t uid;
71
+ uint8_t abstract;
72
+ uint8_t mutabl;
73
+ uint8_t hasfreetypevars;
74
+ uint8_t isconcretetype;
75
+ uint8_t isdispatchtuple;
76
+ uint8_t isbitstype;
77
+ uint8_t zeroinit;
78
+ uint8_t isinlinealloc;
79
+ void *struct_decl;
80
+ void *ditype;
81
+ } jl_datatype_t;
82
+
83
+ struct julia_api_table {
84
+ int (* jl_is_initialized)(void);
85
+ void (* jl_init)(void);
86
+ char const * (* jl_ver_string)(void);
87
+ jl_datatype_t *jl_bool_type;
88
+ jl_datatype_t *jl_char_type;
89
+ jl_datatype_t *jl_string_type;
90
+ jl_datatype_t *jl_int8_type;
91
+ jl_datatype_t *jl_uint8_type;
92
+ jl_datatype_t *jl_int16_type;
93
+ jl_datatype_t *jl_uint16_type;
94
+ jl_datatype_t *jl_int32_type;
95
+ jl_datatype_t *jl_uint32_type;
96
+ jl_datatype_t *jl_int64_type;
97
+ jl_datatype_t *jl_uint64_type;
98
+ jl_datatype_t *jl_float16_type;
99
+ jl_datatype_t *jl_float32_type;
100
+ jl_datatype_t *jl_float64_type;
101
+ jl_value_t * (* jl_eval_string)(const char *str);
102
+ jl_value_t * (* jl_typeof)(jl_value_t *v);
103
+ const char * (* jl_typeof_str)(jl_value_t *v);
104
+ const char * (* jl_string_ptr)(jl_value_t *s);
105
+ int8_t (* jl_unbox_bool)(jl_value_t *v);
106
+ int8_t (* jl_unbox_int8)(jl_value_t *v);
107
+ uint8_t (* jl_unbox_uint8)(jl_value_t *v);
108
+ int16_t (* jl_unbox_int16)(jl_value_t *v);
109
+ uint16_t (* jl_unbox_uint16)(jl_value_t *v);
110
+ int32_t (* jl_unbox_int32)(jl_value_t *v);
111
+ uint32_t (* jl_unbox_uint32)(jl_value_t *v);
112
+ int64_t (* jl_unbox_int64)(jl_value_t *v);
113
+ uint64_t (* jl_unbox_uint64)(jl_value_t *v);
114
+ float (* jl_unbox_float32)(jl_value_t *v);
115
+ double (* jl_unbox_float64)(jl_value_t *v);
116
+ };
117
+
118
+ struct julia_api_table *julia_get_api_table(void);
119
+ #define JULIA_API(name) (julia_get_api_table()->name)
120
+
121
+ void julia_init_libjulia(void);
122
+
123
+ extern VALUE julia_mJulia;
124
+ extern VALUE julia_mLibJulia;
125
+ #endif /* JULIA_INTERNAL_H */
@@ -0,0 +1,253 @@
1
+ #include "julia_internal.h"
2
+
3
+ VALUE julia_mLibJulia;
4
+ VALUE julia_eAPINotFound;
5
+ struct julia_api_table api_table;
6
+ jl_value_t *ans;
7
+ int8_t ans_bool;
8
+
9
+ struct julia_api_table *
10
+ julia_get_api_table(void)
11
+ {
12
+ return &api_table;
13
+ }
14
+
15
+ struct lookup_api_args {
16
+ VALUE handle;
17
+ char const *name;
18
+ };
19
+
20
+ static VALUE
21
+ lookup_libjulia_api_0(struct lookup_api_args *args)
22
+ {
23
+ return rb_funcall(args->handle, rb_intern("sym"), 1, rb_str_new2(args->name));
24
+ }
25
+
26
+ static void *
27
+ lookup_libjulia_api(VALUE handle, char const *name)
28
+ {
29
+ struct lookup_api_args arg;
30
+ VALUE addr;
31
+ int state;
32
+
33
+ arg.handle = handle;
34
+ arg.name = name;
35
+ addr = rb_protect((VALUE (*)(VALUE))lookup_libjulia_api_0, (VALUE)&arg, &state);
36
+ return (state || NIL_P(addr)) ? NULL : NUM2PTR(addr);
37
+ }
38
+
39
+ static void
40
+ init_api_table(VALUE handle)
41
+ {
42
+ #define LOOKUP_API_ENTRY(api_name) lookup_libjulia_api(handle, #api_name)
43
+ #define CHECK_API_ENTRY(api_name) (LOOKUP_API_ENTRY(api_name) != NULL)
44
+ #define INIT_API_TABLE_ENTRY2(member_name, api_name) do { \
45
+ void *fptr = LOOKUP_API_ENTRY(api_name); \
46
+ if (!fptr) { \
47
+ rb_raise(julia_eAPINotFound, "Unable to find the required symbol in libjulia: %s", #api_name); \
48
+ } \
49
+ ((api_table).member_name) = fptr; \
50
+ } while (0)
51
+ #define INIT_API_TABLE_ENTRY(api_name) INIT_API_TABLE_ENTRY2(api_name, api_name)
52
+
53
+ if (CHECK_API_ENTRY(jl_init)) {
54
+ INIT_API_TABLE_ENTRY(jl_init);
55
+ }
56
+ else {
57
+ INIT_API_TABLE_ENTRY2(jl_init, jl_init__threading);
58
+ }
59
+
60
+ INIT_API_TABLE_ENTRY(jl_is_initialized);
61
+ INIT_API_TABLE_ENTRY(jl_ver_string);
62
+
63
+ INIT_API_TABLE_ENTRY(jl_bool_type);
64
+ INIT_API_TABLE_ENTRY(jl_char_type);
65
+ INIT_API_TABLE_ENTRY(jl_string_type);
66
+ INIT_API_TABLE_ENTRY(jl_int8_type);
67
+ INIT_API_TABLE_ENTRY(jl_uint8_type);
68
+ INIT_API_TABLE_ENTRY(jl_int16_type);
69
+ INIT_API_TABLE_ENTRY(jl_uint16_type);
70
+ INIT_API_TABLE_ENTRY(jl_int32_type);
71
+ INIT_API_TABLE_ENTRY(jl_uint32_type);
72
+ INIT_API_TABLE_ENTRY(jl_int64_type);
73
+ INIT_API_TABLE_ENTRY(jl_uint64_type);
74
+ INIT_API_TABLE_ENTRY(jl_float16_type);
75
+ INIT_API_TABLE_ENTRY(jl_float32_type);
76
+ INIT_API_TABLE_ENTRY(jl_float64_type);
77
+ INIT_API_TABLE_ENTRY(jl_eval_string);
78
+ INIT_API_TABLE_ENTRY(jl_typeof);
79
+ INIT_API_TABLE_ENTRY(jl_typeof_str);
80
+ INIT_API_TABLE_ENTRY(jl_string_ptr);
81
+ INIT_API_TABLE_ENTRY(jl_unbox_bool);
82
+ INIT_API_TABLE_ENTRY(jl_unbox_int8);
83
+ INIT_API_TABLE_ENTRY(jl_unbox_uint8);
84
+ INIT_API_TABLE_ENTRY(jl_unbox_int16);
85
+ INIT_API_TABLE_ENTRY(jl_unbox_uint16);
86
+ INIT_API_TABLE_ENTRY(jl_unbox_int32);
87
+ INIT_API_TABLE_ENTRY(jl_unbox_uint32);
88
+ INIT_API_TABLE_ENTRY(jl_unbox_int64);
89
+ INIT_API_TABLE_ENTRY(jl_unbox_uint64);
90
+ INIT_API_TABLE_ENTRY(jl_unbox_float32);
91
+ INIT_API_TABLE_ENTRY(jl_unbox_float64);
92
+ }
93
+
94
+ int
95
+ jl_typeis(jl_value_t *v, jl_datatype_t *t){
96
+ return ((jl_typename_t *)JULIA_API(jl_typeof)(v) == t->name);
97
+ }
98
+
99
+ int
100
+ jl_is_bool(jl_value_t *v)
101
+ {
102
+ return jl_typeis(v, JULIA_API(jl_bool_type));
103
+ }
104
+
105
+ int
106
+ jl_is_char(jl_value_t *v)
107
+ {
108
+ return jl_typeis(v, JULIA_API(jl_char_type));
109
+ }
110
+
111
+ int
112
+ jl_is_string(jl_value_t *v)
113
+ {
114
+ return jl_typeis(v, JULIA_API(jl_string_type));
115
+ }
116
+
117
+ int
118
+ jl_is_int8(jl_value_t *v)
119
+ {
120
+ return jl_typeis(v, JULIA_API(jl_int8_type));
121
+ }
122
+
123
+ int
124
+ jl_is_uint8(jl_value_t *v)
125
+ {
126
+ return jl_typeis(v, JULIA_API(jl_uint8_type));
127
+ }
128
+
129
+ int
130
+ jl_is_int16(jl_value_t *v)
131
+ {
132
+ return jl_typeis(v, JULIA_API(jl_int16_type));
133
+ }
134
+
135
+ int
136
+ jl_is_uint16(jl_value_t *v)
137
+ {
138
+ return jl_typeis(v, JULIA_API(jl_uint16_type));
139
+ }
140
+
141
+ int
142
+ jl_is_int32(jl_value_t *v)
143
+ {
144
+ return jl_typeis(v, JULIA_API(jl_int32_type));
145
+ }
146
+
147
+ int
148
+ jl_is_uint32(jl_value_t *v)
149
+ {
150
+ return jl_typeis(v, JULIA_API(jl_uint32_type));
151
+ }
152
+
153
+ int
154
+ jl_is_int64(jl_value_t *v)
155
+ {
156
+ return jl_typeis(v, JULIA_API(jl_int64_type));
157
+ }
158
+
159
+ int
160
+ jl_is_uint64(jl_value_t *v)
161
+ {
162
+ return jl_typeis(v, JULIA_API(jl_uint64_type));
163
+ }
164
+
165
+ int
166
+ jl_is_float16(jl_value_t *v)
167
+ {
168
+ return jl_typeis(v, JULIA_API(jl_float16_type));
169
+ }
170
+
171
+ int
172
+ jl_is_float32(jl_value_t *v)
173
+ {
174
+ return jl_typeis(v, JULIA_API(jl_float32_type));
175
+ }
176
+
177
+ int
178
+ jl_is_float64(jl_value_t *v)
179
+ {
180
+ return jl_typeis(v, JULIA_API(jl_float64_type));
181
+ }
182
+
183
+ static VALUE
184
+ jl_eval_string(VALUE handle, VALUE arg)
185
+ {
186
+ Check_Type(arg, T_STRING);
187
+ ans = JULIA_API(jl_eval_string)(StringValuePtr(arg));
188
+ if (jl_is_string(ans)) {
189
+ return rb_str_new2(JULIA_API(jl_string_ptr)(ans));
190
+ }
191
+ if (jl_is_bool(ans)) {
192
+ ans_bool = JULIA_API(jl_unbox_bool)(ans);
193
+ if (ans_bool == 1){
194
+ return Qtrue;
195
+ }else{
196
+ return Qfalse;
197
+ }
198
+ }
199
+ if (jl_is_int8(ans)) {
200
+ return INT2NUM(JULIA_API(jl_unbox_int8)(ans));
201
+ }
202
+ if (jl_is_uint8(ans)) {
203
+ return INT2NUM(JULIA_API(jl_unbox_uint8)(ans));
204
+ }
205
+ if (jl_is_int16(ans)) {
206
+ return INT2NUM(JULIA_API(jl_unbox_int16)(ans));
207
+ }
208
+ if (jl_is_uint16(ans)) {
209
+ return INT2NUM(JULIA_API(jl_unbox_uint16)(ans));
210
+ }
211
+ if (jl_is_int32(ans)) {
212
+ return INT2NUM(JULIA_API(jl_unbox_int32)(ans));
213
+ }
214
+ if (jl_is_uint32(ans)) {
215
+ return INT2NUM(JULIA_API(jl_unbox_uint32)(ans));
216
+ }
217
+ if (jl_is_int64(ans)) {
218
+ return INT2NUM(JULIA_API(jl_unbox_int64)(ans));
219
+ }
220
+ if (jl_is_uint64(ans)) {
221
+ return INT2NUM(JULIA_API(jl_unbox_uint64)(ans));
222
+ }
223
+ if (jl_is_float32(ans)) {
224
+ return DBL2NUM(JULIA_API(jl_unbox_float32)(ans));
225
+ }
226
+ if (jl_is_float64(ans)) {
227
+ return DBL2NUM(JULIA_API(jl_unbox_float64)(ans));
228
+ }
229
+ return rb_str_new2(JULIA_API(jl_typeof_str)(ans));
230
+ }
231
+
232
+ static void
233
+ define_JULIA_VERSION(void)
234
+ {
235
+ char const *version = JULIA_API(jl_ver_string)();
236
+ rb_define_const(julia_mLibJulia, "JULIA_VERSION", rb_usascii_str_new_static(version, strlen(version)));
237
+ }
238
+
239
+ void
240
+ julia_init_libjulia(void)
241
+ {
242
+ VALUE handle;
243
+ julia_mLibJulia = rb_const_get_at(julia_mJulia, rb_intern("LibJulia"));
244
+ handle = rb_funcall(julia_mLibJulia, rb_intern("handle"), 0);
245
+ rb_define_module_function(julia_mLibJulia, "jl_eval_string", jl_eval_string, 1);
246
+ init_api_table(handle);
247
+
248
+ if (JULIA_API(jl_is_initialized)() == 0) {
249
+ JULIA_API(jl_init)();
250
+ }
251
+
252
+ define_JULIA_VERSION();
253
+ }
@@ -1,5 +1,5 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+
2
+ lib = File.expand_path('lib', __dir__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'julia/version'
5
5
 
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Kenta Murata"]
10
10
  spec.email = ["mrkn@cookpad.com"]
11
11
 
12
- spec.summary = %q{Julia on Ruby}
13
- spec.description = %q{Julia on Ruby}
12
+ spec.summary = 'Julia on Ruby'
13
+ spec.description = 'Julia on Ruby'
14
14
  spec.homepage = "https://github.com/mrkn/ruby-julia"
15
15
  spec.license = "MIT"
16
16
 
@@ -21,9 +21,11 @@ Gem::Specification.new do |spec|
21
21
  spec.bindir = "exe"
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
- spec.extensions << 'ext/julia/extconf.rb'
25
24
 
26
25
  spec.add_development_dependency "bundler", "~> 1.10"
26
+ spec.add_development_dependency "pry"
27
+ spec.add_development_dependency "pry-byebug"
27
28
  spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "rake-compiler"
28
30
  spec.add_development_dependency "rspec"
29
31
  end
@@ -0,0 +1,12 @@
1
+ module Julia
2
+ require 'julia/version'
3
+ require 'julia/libjulia'
4
+ require 'julia/init'
5
+
6
+ module_function
7
+
8
+ def eval(str)
9
+ Julia.init unless LibJulia.respond_to? :jl_eval_string
10
+ LibJulia.jl_eval_string(str)
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module Julia
2
+ class Error < StandardError
3
+ end
4
+
5
+ class JuliaNotFound < Error
6
+ end
7
+ end
@@ -0,0 +1,49 @@
1
+ module Julia
2
+ def self.const_missing(name)
3
+ case name
4
+ when :JULIA_VERSION
5
+ Julia.init
6
+ const_get(name)
7
+ else
8
+ super
9
+ end
10
+ end
11
+
12
+ module LibJulia
13
+ def self.const_missing(name)
14
+ case name
15
+ when :JULIA_VERSION
16
+ Julia.init
17
+ const_get(name)
18
+ else
19
+ super
20
+ end
21
+ end
22
+ end
23
+
24
+ def self.init(julia = ENV['JULIA'])
25
+ return false if LibJulia.instance_variable_defined? :@handle
26
+ class << Julia
27
+ remove_method :const_missing
28
+ end
29
+ class << Julia::LibJulia
30
+ remove_method :const_missing
31
+ end
32
+
33
+ LibJulia.instance_variable_set :@handle, LibJulia::Finder.find_libjulia(julia)
34
+ class << LibJulia
35
+ undef_method :handle
36
+ attr_reader :handle
37
+ end
38
+
39
+ begin
40
+ major, minor, _ = RUBY_VERSION.split('.')
41
+ require "#{major}.#{minor}/julia.so"
42
+ rescue LoadError
43
+ require 'julia.so'
44
+ end
45
+
46
+ const_set(:JULIA_VERSION, LibJulia::JULIA_VERSION)
47
+ true
48
+ end
49
+ end
@@ -0,0 +1,18 @@
1
+ module Julia
2
+ module LibJulia
3
+ require 'julia/libjulia/finder'
4
+
5
+ def self.load_lib
6
+ require 'julia/libjulia/finder'
7
+ lib_path = Finder.find_libjulia
8
+ Fiddle::Handle.new(lib_path[0], Fiddle::Handle::RTLD_LAZY | Fiddle::Handle::RTLD_GLOBAL)
9
+ end
10
+
11
+ def self.handle
12
+ # NOTE: Julia.init redefine this method.
13
+ # See julia/init.rb for the detail.
14
+ Julia.init
15
+ handle
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,102 @@
1
+ require 'julia/error'
2
+ require 'fiddle'
3
+
4
+ module Julia
5
+ module LibJulia
6
+ module Finder
7
+ case RUBY_PLATFORM
8
+ when /cygwin/
9
+ libprefix = 'cyg'
10
+ libsuffix = 'dll'
11
+ when /mingw/, /mswin/
12
+ libprefix = ''
13
+ libsuffix = 'dll'
14
+ when /darwin/
15
+ libsuffix = 'dylib'
16
+ end
17
+
18
+ LIBPREFIX = libprefix || 'lib'
19
+ LIBSUFFIX = libsuffix || 'so'
20
+
21
+ class << self
22
+ DEFAULT_JULIA = -'julia'
23
+
24
+ def find_libjulia(julia = nil)
25
+ debug_report "find_libjulia(#{julia.inspect})"
26
+ julia_cmd, julia_config = investigate_julia(julia)
27
+
28
+ libpath = File.join(julia_config[:libdir], "libjulia.#{LIBSUFFIX}")
29
+ if File.file? libpath
30
+ begin
31
+ return dlopen(libpath)
32
+ rescue Fiddle::DLError
33
+ debug_report "#{$!.class}: #{$!.message}"
34
+ else
35
+ debug_report "Success to dlopen #{fullname}"
36
+ end
37
+ else
38
+ debug_report "Unable to find #{fullname}"
39
+ end
40
+
41
+ raise Julia::JuliaNotFound
42
+ end
43
+
44
+ def investigate_julia(julia = nil)
45
+ julia ||= DEFAULT_JULIA
46
+ Array(julia).each do |julia_cmd|
47
+ julia_config = run_julia_investigator(julia_cmd)
48
+ return [julia_cmd, julia_config] unless julia_config.empty?
49
+ end
50
+ rescue
51
+ debug_report "investigate_julia: (#{$!.class}) #{$!.message}"
52
+ raise Julia::JuliaNotFound
53
+ else
54
+ raise Julia::JuliaNotFound
55
+ end
56
+
57
+ def run_julia_investigator(julia_cmd)
58
+ debug_report "run_julia_investigator(#{julia_cmd})"
59
+ IO.popen({}, [julia_cmd, julia_investigator_jl], 'r') do |io|
60
+ {}.tap do |config|
61
+ io.each_line do |line|
62
+ next unless line =~ /: /
63
+ key, value = line.chomp.split(': ', 2)
64
+ case value
65
+ when 'true', 'false'
66
+ value = (value == 'true')
67
+ end
68
+ config[key.to_sym] = value if value != 'nothing'
69
+ end
70
+ end
71
+ end
72
+ rescue Errno::ENOENT
73
+ raise Julia::JuliaNotFound
74
+ end
75
+
76
+ def julia_investigator_jl
77
+ File.expand_path('../investigator.jl', __FILE__)
78
+ end
79
+
80
+ private
81
+
82
+ def dlopen(path)
83
+ # NOTE: libjulia needs to be dlopened with RTLD_GLOBAL.
84
+ # Fiddle.dlopen(path) is same as Fiddle::Handle.new(path),
85
+ # and Fiddle::Handle.new defaultly specifies RTLD_GLOBAL.
86
+ Fiddle.dlopen(path).tap do |handle|
87
+ debug_report "dlopen(#{path.inspect}) = #{handle.inspect}" if handle
88
+ end
89
+ end
90
+
91
+ def debug_report(message)
92
+ return unless debug?
93
+ $stderr.puts "DEBUG(find_libjulia) #{message}"
94
+ end
95
+
96
+ def debug?
97
+ @debug_p ||= (ENV['RUBY_JULIA_DEBUG_FIND_LIBJULIA'] == '1')
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,18 @@
1
+ # See https://github.com/JuliaLang/julia/pull/25102
2
+ if VERSION < v"0.7.0-DEV.3073"
3
+ bindir = JULIA_HOME
4
+ else
5
+ bindir = Sys.BINDIR
6
+ end
7
+
8
+ if VERSION >= v"0.7.0-DEV.3382"
9
+ using Libdl
10
+ end
11
+
12
+ println("VERSION: $(VERSION)")
13
+
14
+ jl_share = abspath(joinpath(bindir, Base.DATAROOTDIR, "julia"))
15
+ println("JL_HOME: $(jl_share)")
16
+
17
+ libdir = abspath(dirname(Libdl.dlpath("libjulia")))
18
+ println("libdir: $(libdir)")
@@ -0,0 +1,59 @@
1
+ function find_library(ruby::AbstractString)
2
+ v = rbexpr(ruby, "RUBY_VERSION", "")
3
+ libs = [ dlprefix*"ruby"*v, dlprefix*"ruby" ]
4
+ lib = rbconfig_expand(ruby, "\$(LIBRUBY_SO)")
5
+ lib != nothing && unshift!(libs, splitext(lib)[1])
6
+ libs = unique(libs)
7
+
8
+ libpaths = [ rbconfig_expand(ruby, "\$(libdir)") ]
9
+ ruby_path = rbexpr(ruby, "RbConfig.ruby")
10
+ if ruby_path != nothing
11
+ if is_windows()
12
+ push!(libpaths, dirname(ruby_path))
13
+ else
14
+ push!(libpaths, joinpath(dirname(dirname(ruby_path)), "lib"))
15
+ end
16
+ end
17
+ if is_apple()
18
+ # TODO: The framework directory of the system ruby should be added in libpaths
19
+ end
20
+
21
+ exec_prefix = rbconfig(ruby, "exec_prefix")
22
+ push!(libpaths, exec_prefix)
23
+ push!(libpaths, joinpath(exec_prefix, "lib"))
24
+
25
+ error_strings = Compat.String[]
26
+
27
+ # find libruby
28
+ for lib in libs
29
+ for libpath in libpaths
30
+ libpath_lib = joinpath(libpath, lib)
31
+ if isfile(libpath_lib*"."*Libdl.dlext)
32
+ try
33
+ return (Libdl.dlopen(libpath_lib,
34
+ Libdl.RTLD_LAZY | Libdl.RTLD_DEEPBIND | Libdl.RTLD_GLOBAL),
35
+ libpath_lib)
36
+ catch e
37
+ push!(error_strings, string("dlopen($libpath_lib) ==> ", e))
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ # find libruby from the system library path
44
+ for lib in libs
45
+ lib = splitext(lib)[1]
46
+ try
47
+ return (Libdl.dlopen(lib, Libdl.RTLD_LAZY | Libdl.RTLD_DEEPBIND | Libdl.RTLD_GLOBAL),
48
+ lib)
49
+ catch e
50
+ push!(error_strings, string("dlopen($lib) ==> ", e))
51
+ end
52
+ end
53
+ end
54
+
55
+ const ruby = "ruby"
56
+
57
+ const (libruby_handle, libruby) = find_library(ruby)
58
+ const programname = rbexpr(ruby, "RbConfig.ruby")
59
+ const ruby_version = convert(VersionNumber, rbexpr(ruby, "RUBY_VERSION"))
@@ -0,0 +1,168 @@
1
+ module Ruby
2
+
3
+ using Compat
4
+
5
+ # startup
6
+ # =======
7
+
8
+ hassym(lib, sym) = Libdl.dlsym_e(lib, sym) != C_NULL
9
+
10
+ function rbexpr(ruby::AbstractString, var::AbstractString)
11
+ val = chomp(readstring(`$ruby -rrbconfig -e "puts $var"`))
12
+ if val == ""
13
+ return nothing
14
+ end
15
+ return val
16
+ end
17
+
18
+ function rbexpr(ruby, var, default)
19
+ val = rbexpr(ruby, var)
20
+ return val == nothing ? default : val
21
+ end
22
+
23
+ function rbconfig(ruby::AbstractString, key::AbstractString)
24
+ return rbexpr(ruby, "RbConfig::CONFIG['$key']")
25
+ end
26
+
27
+ function rbconfig_expand(ruby::AbstractString, make_expr::AbstractString)
28
+ return rbexpr(ruby, "RbConfig.expand('$make_expr')")
29
+ end
30
+
31
+ const dlprefix = is_windows() ? "" : "lib"
32
+
33
+ immutable Dl_info
34
+ dli_fname::Ptr{UInt8}
35
+ dli_fbase::Ptr{Void}
36
+ dli_sname::Ptr{UInt8}
37
+ dli_saddr::Ptr{Void}
38
+ end
39
+
40
+ proc_handle = unsafe_load(@static is_windows() ?
41
+ cglobal(:jl_exe_handle, Ptr{Void}) :
42
+ cglobal(:jl_dl_handle, Ptr{Void}))
43
+
44
+ symbols_present = false
45
+ @static if is_windows()
46
+ EnumProcessModules(hProcess, lphModule, cb, lpcbNeeded) =
47
+ ccall(:K32EnumProcessModules, stdcall, Bool,
48
+ (Ptr{Void}, Ptr{Ptr{Void}}, UInt32, Ptr{UInt32}),
49
+ hProcess, lphModule, cb, lpcbNeeded)
50
+
51
+ lpcbNeeded = Ref{UInt32}()
52
+ handles = Vector{Ptr{Void}}(20)
53
+ if EnumProcessModules(proc_handle, handles, sizeof(handles), lpcbNeeded) == 0
54
+ resize!(handles, div(lpcbNeeded[], sizeof(Ptr{Void})))
55
+ EnumProcessModules(proc_handle, handles, sizeof(handles), lpcbNeeded)
56
+ end
57
+ # Try to find ruby if it's in the current process
58
+ for handle in handles
59
+ sym = ccall(:GetProcAddress, stdcall, Ptr{Void},
60
+ (Ptr{Void}, Ptr{UInt8}), handle, "rb_sysinit")
61
+ sym != C_NULL || continue
62
+ symbols_present = true
63
+ global libruby_handle = handle
64
+ break
65
+ end
66
+ else
67
+ symbols_present = hassym(proc_handle, :rb_sysinit)
68
+ end
69
+
70
+ if !symbols_present
71
+ # Ruby not present. Load libruby here.
72
+ include(joinpath(dirname(@__FILE__), "load_libruby.jl"))
73
+ else
74
+ @static if is_windows()
75
+ pathbuf = Vector{UInt16}(1024)
76
+ ret = ccall(:GetModuleFileNameW, stdcall, UInt32,
77
+ (Ptr{Void}, Ptr{UInt16}, UInt32),
78
+ libruby_handle, pathbuf, length(pathbuf))
79
+ @assert ret != 0
80
+ libname = String(Base.transcode(UInt8, pathbuf[1:findfirst(pathbuf, 0)-1]))
81
+ else
82
+ libruby_handle = proc_handle
83
+ # Now determine the name of the ruby library that these symbols are from
84
+ some_address_in_libruby = Libdl.dlsym(libruby_handle, :rb_sysinit)
85
+ dlinfo = Ref{Dl_info}()
86
+ ccall(:dladdr, Cint, (Ptr{Void}, Ptr{Dl_info}), some_address_in_libruby, dlinfo)
87
+ libname = unsafe_string(dlinfo[].dli_fname)
88
+ end
89
+ if Libdl.dlopen_e(libname) != C_NULL
90
+ const libruby = libname
91
+ else
92
+ const libruby = nothing
93
+ end
94
+ end
95
+
96
+ if libruby == nothing
97
+ macro rbsym(func)
98
+ :($func)
99
+ end
100
+ macro rbglobal(name)
101
+ :(cglobal($name))
102
+ end
103
+ else
104
+ macro rbsym(func)
105
+ :(($func, libruby))
106
+ end
107
+ macro rbglobal(name)
108
+ :(cglobal(($name, libruby)))
109
+ end
110
+ end
111
+
112
+ @static if sizeof(Clong) == sizeof(Ptr{Void})
113
+ typealias VALUE Culong
114
+ typealias ID Culong
115
+ typealias SIGNED_VALUE Clong
116
+ else
117
+ @static if sizeof(Clonglong) == sizeof(Ptr{Void})
118
+ typealias VALUE Culonglong
119
+ typealias ID Culonglong
120
+ typealias SIGNED_VALUE Clonglong
121
+ else
122
+ error("shouldn't be reached here")
123
+ end
124
+ end
125
+
126
+ # definitions
127
+ # -----------
128
+
129
+ # special constants - i.e. non-zero and non-fixnum constants
130
+
131
+ # NOTE: Ruby.jl assumes ruby was built with flonum support.
132
+
133
+ const Qfalse = VALUE(0x00) # ...0000 0000
134
+ const Qtrue = VALUE(0x14) # ...0001 0100
135
+ const Qnil = VALUE(0x08) # ...0000 1000
136
+ const Qundef = VALUE(0x34) # ...0011 0100
137
+
138
+ const IMMEDIATE_MASK = VALUE(0x07)
139
+ const FIXNUM_FLAG = VALUE(0x01) # ...xxxx xxx1
140
+ const FLONUM_MASK = VALUE(0x03)
141
+ const FLONUM_FLAG = VALUE(0x02) # ...xxxx xx10
142
+ const SYMBOL_FLAG = VALUE(0x0c) # ...0000 1100
143
+
144
+ const SPECIAL_SHIFT = VALUE(8)
145
+
146
+ const FIXNUM_MAX = typemax(Clong) >> 1
147
+ const FIXNUM_MIN = typemin(Clong) >> 1
148
+
149
+ LONG2FIX(i::Clong) = ((VALUE(i) << 1) | FIXNUM_FLAG)
150
+
151
+ FIX2LONG(x::VALUE) = Clong(SIGNED_VALUE(x) >> 1)
152
+ FIX2ULONG(x::VALUE) = Culong(FIX2LONG(x))
153
+ FIXNUM_P(f::SIGNED_VALUE) = (f & FIXNUM_FLAG) != 0
154
+ POSFIXABLE(f::Integer) = f < FIXNUM_MAX + 1
155
+ NEGFIXABLE(f::Integer) = f >= FIXNUM_MIN
156
+ FIXABLE(f::Integer) = POSFIXABLE(f) && NEGFIXABLE(f)
157
+
158
+ # initialize
159
+ # ----------
160
+
161
+ function __init__()
162
+ already_initialized = 0 != unsafe_load(Ptr{VALUE}(@rbglobal(:rb_cObject)))
163
+ if !already_initialized
164
+ ccall((@rbsym :ruby_init), Void, ())
165
+ end
166
+ end
167
+
168
+ end # module Ruby
@@ -1,3 +1,3 @@
1
1
  module Julia
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: julia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenta Murata
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-07-13 00:00:00.000000000 Z
11
+ date: 2018-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry-byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: rake
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +66,20 @@ dependencies:
38
66
  - - "~>"
39
67
  - !ruby/object:Gem::Version
40
68
  version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake-compiler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
41
83
  - !ruby/object:Gem::Dependency
42
84
  name: rspec
43
85
  requirement: !ruby/object:Gem::Requirement
@@ -56,8 +98,7 @@ description: Julia on Ruby
56
98
  email:
57
99
  - mrkn@cookpad.com
58
100
  executables: []
59
- extensions:
60
- - ext/julia/extconf.rb
101
+ extensions: []
61
102
  extra_rdoc_files: []
62
103
  files:
63
104
  - ".gitignore"
@@ -72,7 +113,17 @@ files:
72
113
  - examples/pkg_status.rb
73
114
  - ext/julia/extconf.rb
74
115
  - ext/julia/julia.c
116
+ - ext/julia/julia_internal.h
117
+ - ext/julia/libjulia.c
75
118
  - julia.gemspec
119
+ - lib/julia.rb
120
+ - lib/julia/error.rb
121
+ - lib/julia/init.rb
122
+ - lib/julia/libjulia.rb
123
+ - lib/julia/libjulia/finder.rb
124
+ - lib/julia/libjulia/investigator.jl
125
+ - lib/julia/load_libruby.jl
126
+ - lib/julia/ruby.jl
76
127
  - lib/julia/version.rb
77
128
  homepage: https://github.com/mrkn/ruby-julia
78
129
  licenses:
@@ -94,9 +145,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
145
  version: '0'
95
146
  requirements: []
96
147
  rubyforge_project:
97
- rubygems_version: 2.4.5
148
+ rubygems_version: 2.7.6
98
149
  signing_key:
99
150
  specification_version: 4
100
151
  summary: Julia on Ruby
101
152
  test_files: []
102
- has_rdoc: