frida 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +84 -84
  3. data/Gemfile +12 -12
  4. data/Gemfile.lock +25 -25
  5. data/LICENSE.txt +21 -21
  6. data/README.md +64 -64
  7. data/Rakefile +20 -20
  8. data/exe/frida +3 -3
  9. data/ext/c_frida/Application.c +79 -79
  10. data/ext/c_frida/Bus.c +91 -91
  11. data/ext/c_frida/Child.c +134 -134
  12. data/ext/c_frida/Compiler.c +0 -0
  13. data/ext/c_frida/Crash.c +0 -0
  14. data/ext/c_frida/Device.c +955 -955
  15. data/ext/c_frida/DeviceManager.c +260 -260
  16. data/ext/c_frida/EndpointParameters.c +0 -0
  17. data/ext/c_frida/FileMonitor.c +0 -0
  18. data/ext/c_frida/GObject.c +0 -0
  19. data/ext/c_frida/IOStream.c +228 -228
  20. data/ext/c_frida/PortalMembership.c +0 -0
  21. data/ext/c_frida/PortalService.c +0 -0
  22. data/ext/c_frida/Process.c +67 -67
  23. data/ext/c_frida/Relay.c +0 -0
  24. data/ext/c_frida/Script.c +221 -221
  25. data/ext/c_frida/Session.c +626 -626
  26. data/ext/c_frida/Spawn.c +53 -53
  27. data/ext/c_frida/c_frida.c +68 -68
  28. data/ext/c_frida/extconf.rb +25 -25
  29. data/ext/c_frida/gutils.c +498 -498
  30. data/ext/c_frida/gvl_bridge.c +131 -131
  31. data/ext/c_frida/inc/Application.h +9 -9
  32. data/ext/c_frida/inc/Bus.h +15 -15
  33. data/ext/c_frida/inc/Child.h +9 -9
  34. data/ext/c_frida/inc/Compiler.h +0 -0
  35. data/ext/c_frida/inc/Crash.h +0 -0
  36. data/ext/c_frida/inc/Device.h +71 -71
  37. data/ext/c_frida/inc/DeviceManager.h +20 -20
  38. data/ext/c_frida/inc/EndpointParameters.h +0 -0
  39. data/ext/c_frida/inc/FileMonitor.h +0 -0
  40. data/ext/c_frida/inc/GObject.h +0 -0
  41. data/ext/c_frida/inc/IOStream.h +29 -29
  42. data/ext/c_frida/inc/PortalMembership.h +0 -0
  43. data/ext/c_frida/inc/PortalService.h +0 -0
  44. data/ext/c_frida/inc/Process.h +9 -9
  45. data/ext/c_frida/inc/Relay.h +0 -0
  46. data/ext/c_frida/inc/Script.h +21 -21
  47. data/ext/c_frida/inc/Session.h +40 -40
  48. data/ext/c_frida/inc/Spawn.h +9 -9
  49. data/ext/c_frida/inc/c_frida.h +129 -129
  50. data/ext/c_frida/inc/gutils.h +21 -21
  51. data/ext/c_frida/inc/gvl_bridge.h +42 -42
  52. data/lib/frida/version.rb +5 -5
  53. data/lib/frida.rb +8 -8
  54. metadata +3 -6
  55. data/frida.gemspec +0 -39
@@ -1,260 +1,260 @@
1
- #include "DeviceManager.h"
2
-
3
- VALUE DeviceManager_from_FridaDeviceManager(FridaDeviceManager *handle)
4
- {
5
- VALUE self;
6
-
7
- if (!handle)
8
- return (Qnil);
9
- self = rb_class_new_instance(0, NULL, cDeviceManager);
10
- GET_GOBJECT_DATA();
11
- d->destroy(d->handle);
12
- d->handle = handle;
13
- return (self);
14
- }
15
-
16
- GVL_FREE_PROXY_FUNC(close_device_manager_err, FridaDeviceManager *device_manager)
17
- {
18
- GError *gerr = NULL;
19
-
20
- frida_device_manager_close_sync(device_manager, NULL, &gerr);
21
- RETURN_GVL_FREE_RESULT(NULL);
22
- }
23
-
24
- GVL_FREE_PROXY_FUNC(close_device_manager, FridaDeviceManager *device_manager)
25
- {
26
- frida_device_manager_close_sync(device_manager, NULL, NULL);
27
- return (NULL);
28
- }
29
-
30
- static void DeviceManager_destroy(void *handle)
31
- {
32
- CALL_GVL_FREE(close_device_manager, handle);
33
- frida_unref(handle);
34
- }
35
-
36
- /*
37
- call-seq:
38
- #close() -> nil
39
- */
40
- static VALUE DeviceManager_close(VALUE self)
41
- {
42
- GET_GOBJECT_DATA();
43
- REQUIRE_GOBJECT_HANDLE();
44
- CALL_GVL_FREE_WITH_RET(void *dummy, close_device_manager_err, d->handle);
45
- return (Qnil);
46
-
47
- GERROR_BLOCK
48
- }
49
-
50
- GVL_FREE_PROXY_FUNC(enumerate_devices_sync, FridaDeviceManager *device_manager)
51
- {
52
- GError *gerr = NULL;
53
- FridaDeviceList * devices;
54
-
55
- devices = frida_device_manager_enumerate_devices_sync(device_manager, NULL, &gerr);
56
- RETURN_GVL_FREE_RESULT(devices);
57
- }
58
-
59
- /*
60
- call-seq:
61
- #enumerate_device() -> Array[Device]
62
- */
63
- static VALUE DeviceManager_enumerate_devices(VALUE self)
64
- {
65
- GET_GOBJECT_DATA();
66
- REQUIRE_GOBJECT_HANDLE();
67
- FridaDeviceList * devices;
68
- int devices_count;
69
- VALUE Devices_arr;
70
-
71
- CALL_GVL_FREE_WITH_RET(devices, enumerate_devices_sync, d->handle);
72
- devices_count = frida_device_list_size(devices);
73
- Devices_arr = rb_ary_new_capa(devices_count);
74
- for (int i = 0; i < devices_count; i++)
75
- rb_ary_store(Devices_arr, i, Device_from_FridaDevice(frida_device_list_get(devices, i)));
76
- frida_unref(devices);
77
- return (Devices_arr);
78
-
79
- GERROR_BLOCK
80
- }
81
-
82
- /*
83
- call-seq:
84
- #get_device_matching() {} -> Device
85
- */
86
- static VALUE DeviceManager_get_device_matching(VALUE self)
87
- {
88
- GET_GOBJECT_DATA();
89
- REQUIRE_GOBJECT_HANDLE();
90
- VALUE block;
91
- VALUE devices, current_device, block_ret;
92
- int devices_count;
93
-
94
- if (!rb_block_given_p()) {
95
- raise_argerror("a block argument is required");
96
- return (Qnil);
97
- }
98
- block = rb_block_proc();
99
- // NOTE: Ruby does not support (currently) setting up a non Ruby created thread to be able
100
- // to call its C APIs, frida_device_manager_get_device_sync() would call our filtering predicate from a frida thread
101
- // which is not created by Ruby, and GET_EC() call in the Ruby's C APIs would return NULL.
102
- // so the filtering is done in this thread that currently holds the GVL, mimicking frida_device_manager_get_device_sync().
103
- devices = rb_funcall(self, rb_intern("enumerate_devices"), 0, NULL);
104
- devices_count = RARRAY_LEN(devices);
105
- for (int i = 0; i < devices_count; i++) {
106
- current_device = rb_ary_entry(devices, i);
107
- block_ret = rb_funcall(block, rb_intern("call"), 1, current_device);
108
- if (block_ret == Qtrue) return (current_device);
109
- }
110
- return (Qnil);
111
- }
112
-
113
- static FridaRemoteDeviceOptions *parse_add_rdevice_kws_to_options(VALUE kws)
114
- {
115
- FridaRemoteDeviceOptions *options;
116
- VALUE cert, origin, token, keepalive_interval;
117
-
118
- options = frida_remote_device_options_new();
119
- cert = rb_hash_aref(kws, ID2SYM(rb_intern("certificate")));
120
- if (!NIL_P(cert)) {
121
- if (!RB_TYPE_P(cert, T_STRING)) {
122
- raise_argerror("certificate should be a string.");
123
- goto error;
124
- }
125
- GTlsCertificate * certificate;
126
- if (!rbGObject_unmarshal_certificate(StringValueCStr(cert), &certificate))
127
- goto error;
128
- frida_remote_device_options_set_certificate(options, certificate);
129
- g_object_unref(certificate);
130
- }
131
- origin = rb_hash_aref(kws, ID2SYM(rb_intern("origin")));
132
- if (!NIL_P(origin)) {
133
- if (!RB_TYPE_P(origin, T_STRING)) {
134
- raise_argerror("origin should be a string.");
135
- goto error;
136
- }
137
- frida_remote_device_options_set_origin(options, StringValueCStr(origin));
138
- }
139
- token = rb_hash_aref(kws, ID2SYM(rb_intern("token")));
140
- if (!NIL_P(token)) {
141
- if (!RB_TYPE_P(token, T_STRING)) {
142
- raise_argerror("token should be a string.");
143
- goto error;
144
- }
145
- frida_remote_device_options_set_token(options, StringValueCStr(token));
146
- }
147
- keepalive_interval = rb_hash_aref(kws, ID2SYM(rb_intern("keepalive_interval")));
148
- if (!NIL_P(keepalive_interval)) {
149
- if (!RB_TYPE_P(keepalive_interval, T_FIXNUM)) {
150
- raise_argerror("keepalive_interval should be a number.");
151
- goto error;
152
- }
153
- frida_remote_device_options_set_keepalive_interval(options, NUM2INT(keepalive_interval));
154
- }
155
- return (options);
156
-
157
- error:
158
- g_object_unref(options);
159
- return (NULL);
160
- }
161
-
162
- GVL_FREE_PROXY_FUNC(add_remote_device_sync, add_remote_device_proxy_args *args)
163
- {
164
- GError *gerr = NULL;
165
- FridaDevice *device;
166
-
167
- device = frida_device_manager_add_remote_device_sync(args->device_manager, args->address, args->options, NULL, &gerr);
168
- RETURN_GVL_FREE_RESULT(device);
169
- }
170
-
171
- /*
172
- call-seq:
173
- #add_remote_device(address, certificate:, origin:, token:, keepalive_interval:) -> Device
174
- */
175
- static VALUE DeviceManager_add_remote_device(int argc, VALUE *argv, VALUE self)
176
- {
177
- GET_GOBJECT_DATA();
178
- REQUIRE_GOBJECT_HANDLE();
179
- VALUE address, kws;
180
- FridaRemoteDeviceOptions *options;
181
- FridaDevice *device;
182
-
183
- rb_scan_args(argc, argv, "1:", &address, &kws);
184
- if (!RB_TYPE_P(address, T_STRING))
185
- return (raise_argerror("address must be a string."), Qnil);
186
- if (NIL_P(kws)) kws = rb_hash_new();
187
- options = parse_add_rdevice_kws_to_options(kws);
188
- if (!options)
189
- return (Qnil);
190
- add_remote_device_proxy_args args = {
191
- .device_manager = d->handle,
192
- .options = options,
193
- .address = StringValueCStr(address)
194
- };
195
- CALL_GVL_FREE_WITH_RET(device, add_remote_device_sync, &args);
196
- g_object_unref(options);
197
- return (Device_from_FridaDevice(device));
198
-
199
- gerror:
200
- g_object_unref(options);
201
- raise_rerror(NULL, _gerr);
202
- return (Qnil);
203
- }
204
-
205
- GVL_FREE_PROXY_FUNC(remove_remote_device_sync, remove_remote_devices_proxy_args *args)
206
- {
207
- GError *gerr = NULL;
208
-
209
- frida_device_manager_remove_remote_device_sync(args->device_manager, args->address, NULL, &gerr);
210
- RETURN_GVL_FREE_RESULT(NULL);
211
- }
212
-
213
- /*
214
- call-seq:
215
- #remove_remote_device(address) -> nil
216
- */
217
- static VALUE DeviceManager_remove_remote_device(VALUE self, VALUE address)
218
- {
219
- GET_GOBJECT_DATA();
220
- REQUIRE_GOBJECT_HANDLE();
221
-
222
- if (!RB_TYPE_P(address, T_STRING)) {
223
- raise_argerror("address should be a string.");
224
- return (Qnil);
225
- }
226
- remove_remote_devices_proxy_args args = {
227
- .device_manager = d->handle,
228
- .address = StringValueCStr(address)
229
- };
230
- CALL_GVL_FREE_WITH_RET(void *dummy, remove_remote_device_sync, &args);
231
- return (Qnil);
232
-
233
- GERROR_BLOCK
234
- }
235
-
236
- /*
237
- call-seq:
238
- #new() -> DeviceManager
239
- */
240
- static VALUE DeviceManager_initialize(VALUE self)
241
- {
242
- GET_GOBJECT_DATA();
243
- d->handle = frida_device_manager_new();
244
- if (!d->handle)
245
- return (raise_rerror("failed to retrieve a device manager.", NULL), Qnil);
246
- d->destroy = DeviceManager_destroy;
247
- return (self);
248
- }
249
-
250
- void define_DeviceManager()
251
- {
252
- cDeviceManager = rb_define_class_under(mCFrida, "DeviceManager", cGObject);
253
-
254
- rb_define_method(cDeviceManager, "initialize", DeviceManager_initialize, 0);
255
- rb_define_method(cDeviceManager, "enumerate_devices", DeviceManager_enumerate_devices, 0);
256
- rb_define_method(cDeviceManager, "get_device_matching", DeviceManager_get_device_matching, 0);
257
- rb_define_method(cDeviceManager, "add_remote_device", DeviceManager_add_remote_device, -1);
258
- rb_define_method(cDeviceManager, "remove_remote_device", DeviceManager_remove_remote_device, 1);
259
- rb_define_method(cDeviceManager, "close", DeviceManager_close, 0);
260
- }
1
+ #include "DeviceManager.h"
2
+
3
+ VALUE DeviceManager_from_FridaDeviceManager(FridaDeviceManager *handle)
4
+ {
5
+ VALUE self;
6
+
7
+ if (!handle)
8
+ return (Qnil);
9
+ self = rb_class_new_instance(0, NULL, cDeviceManager);
10
+ GET_GOBJECT_DATA();
11
+ d->destroy(d->handle);
12
+ d->handle = handle;
13
+ return (self);
14
+ }
15
+
16
+ GVL_FREE_PROXY_FUNC(close_device_manager_err, FridaDeviceManager *device_manager)
17
+ {
18
+ GError *gerr = NULL;
19
+
20
+ frida_device_manager_close_sync(device_manager, NULL, &gerr);
21
+ RETURN_GVL_FREE_RESULT(NULL);
22
+ }
23
+
24
+ GVL_FREE_PROXY_FUNC(close_device_manager, FridaDeviceManager *device_manager)
25
+ {
26
+ frida_device_manager_close_sync(device_manager, NULL, NULL);
27
+ return (NULL);
28
+ }
29
+
30
+ static void DeviceManager_destroy(void *handle)
31
+ {
32
+ CALL_GVL_FREE(close_device_manager, handle);
33
+ frida_unref(handle);
34
+ }
35
+
36
+ /*
37
+ call-seq:
38
+ #close() -> nil
39
+ */
40
+ static VALUE DeviceManager_close(VALUE self)
41
+ {
42
+ GET_GOBJECT_DATA();
43
+ REQUIRE_GOBJECT_HANDLE();
44
+ CALL_GVL_FREE_WITH_RET(void *dummy, close_device_manager_err, d->handle);
45
+ return (Qnil);
46
+
47
+ GERROR_BLOCK
48
+ }
49
+
50
+ GVL_FREE_PROXY_FUNC(enumerate_devices_sync, FridaDeviceManager *device_manager)
51
+ {
52
+ GError *gerr = NULL;
53
+ FridaDeviceList * devices;
54
+
55
+ devices = frida_device_manager_enumerate_devices_sync(device_manager, NULL, &gerr);
56
+ RETURN_GVL_FREE_RESULT(devices);
57
+ }
58
+
59
+ /*
60
+ call-seq:
61
+ #enumerate_device() -> Array[Device]
62
+ */
63
+ static VALUE DeviceManager_enumerate_devices(VALUE self)
64
+ {
65
+ GET_GOBJECT_DATA();
66
+ REQUIRE_GOBJECT_HANDLE();
67
+ FridaDeviceList * devices;
68
+ int devices_count;
69
+ VALUE Devices_arr;
70
+
71
+ CALL_GVL_FREE_WITH_RET(devices, enumerate_devices_sync, d->handle);
72
+ devices_count = frida_device_list_size(devices);
73
+ Devices_arr = rb_ary_new_capa(devices_count);
74
+ for (int i = 0; i < devices_count; i++)
75
+ rb_ary_store(Devices_arr, i, Device_from_FridaDevice(frida_device_list_get(devices, i)));
76
+ frida_unref(devices);
77
+ return (Devices_arr);
78
+
79
+ GERROR_BLOCK
80
+ }
81
+
82
+ /*
83
+ call-seq:
84
+ #get_device_matching() {} -> Device
85
+ */
86
+ static VALUE DeviceManager_get_device_matching(VALUE self)
87
+ {
88
+ GET_GOBJECT_DATA();
89
+ REQUIRE_GOBJECT_HANDLE();
90
+ VALUE block;
91
+ VALUE devices, current_device, block_ret;
92
+ int devices_count;
93
+
94
+ if (!rb_block_given_p()) {
95
+ raise_argerror("a block argument is required");
96
+ return (Qnil);
97
+ }
98
+ block = rb_block_proc();
99
+ // NOTE: Ruby does not support (currently) setting up a non Ruby created thread to be able
100
+ // to call its C APIs, frida_device_manager_get_device_sync() would call our filtering predicate from a frida thread
101
+ // which is not created by Ruby, and GET_EC() call in the Ruby's C APIs would return NULL.
102
+ // so the filtering is done in this thread that currently holds the GVL, mimicking frida_device_manager_get_device_sync().
103
+ devices = rb_funcall(self, rb_intern("enumerate_devices"), 0, NULL);
104
+ devices_count = RARRAY_LEN(devices);
105
+ for (int i = 0; i < devices_count; i++) {
106
+ current_device = rb_ary_entry(devices, i);
107
+ block_ret = rb_funcall(block, rb_intern("call"), 1, current_device);
108
+ if (block_ret == Qtrue) return (current_device);
109
+ }
110
+ return (Qnil);
111
+ }
112
+
113
+ static FridaRemoteDeviceOptions *parse_add_rdevice_kws_to_options(VALUE kws)
114
+ {
115
+ FridaRemoteDeviceOptions *options;
116
+ VALUE cert, origin, token, keepalive_interval;
117
+
118
+ options = frida_remote_device_options_new();
119
+ cert = rb_hash_aref(kws, ID2SYM(rb_intern("certificate")));
120
+ if (!NIL_P(cert)) {
121
+ if (!RB_TYPE_P(cert, T_STRING)) {
122
+ raise_argerror("certificate should be a string.");
123
+ goto error;
124
+ }
125
+ GTlsCertificate * certificate;
126
+ if (!rbGObject_unmarshal_certificate(StringValueCStr(cert), &certificate))
127
+ goto error;
128
+ frida_remote_device_options_set_certificate(options, certificate);
129
+ g_object_unref(certificate);
130
+ }
131
+ origin = rb_hash_aref(kws, ID2SYM(rb_intern("origin")));
132
+ if (!NIL_P(origin)) {
133
+ if (!RB_TYPE_P(origin, T_STRING)) {
134
+ raise_argerror("origin should be a string.");
135
+ goto error;
136
+ }
137
+ frida_remote_device_options_set_origin(options, StringValueCStr(origin));
138
+ }
139
+ token = rb_hash_aref(kws, ID2SYM(rb_intern("token")));
140
+ if (!NIL_P(token)) {
141
+ if (!RB_TYPE_P(token, T_STRING)) {
142
+ raise_argerror("token should be a string.");
143
+ goto error;
144
+ }
145
+ frida_remote_device_options_set_token(options, StringValueCStr(token));
146
+ }
147
+ keepalive_interval = rb_hash_aref(kws, ID2SYM(rb_intern("keepalive_interval")));
148
+ if (!NIL_P(keepalive_interval)) {
149
+ if (!RB_TYPE_P(keepalive_interval, T_FIXNUM)) {
150
+ raise_argerror("keepalive_interval should be a number.");
151
+ goto error;
152
+ }
153
+ frida_remote_device_options_set_keepalive_interval(options, NUM2INT(keepalive_interval));
154
+ }
155
+ return (options);
156
+
157
+ error:
158
+ g_object_unref(options);
159
+ return (NULL);
160
+ }
161
+
162
+ GVL_FREE_PROXY_FUNC(add_remote_device_sync, add_remote_device_proxy_args *args)
163
+ {
164
+ GError *gerr = NULL;
165
+ FridaDevice *device;
166
+
167
+ device = frida_device_manager_add_remote_device_sync(args->device_manager, args->address, args->options, NULL, &gerr);
168
+ RETURN_GVL_FREE_RESULT(device);
169
+ }
170
+
171
+ /*
172
+ call-seq:
173
+ #add_remote_device(address, certificate:, origin:, token:, keepalive_interval:) -> Device
174
+ */
175
+ static VALUE DeviceManager_add_remote_device(int argc, VALUE *argv, VALUE self)
176
+ {
177
+ GET_GOBJECT_DATA();
178
+ REQUIRE_GOBJECT_HANDLE();
179
+ VALUE address, kws;
180
+ FridaRemoteDeviceOptions *options;
181
+ FridaDevice *device;
182
+
183
+ rb_scan_args(argc, argv, "1:", &address, &kws);
184
+ if (!RB_TYPE_P(address, T_STRING))
185
+ return (raise_argerror("address must be a string."), Qnil);
186
+ if (NIL_P(kws)) kws = rb_hash_new();
187
+ options = parse_add_rdevice_kws_to_options(kws);
188
+ if (!options)
189
+ return (Qnil);
190
+ add_remote_device_proxy_args args = {
191
+ .device_manager = d->handle,
192
+ .options = options,
193
+ .address = StringValueCStr(address)
194
+ };
195
+ CALL_GVL_FREE_WITH_RET(device, add_remote_device_sync, &args);
196
+ g_object_unref(options);
197
+ return (Device_from_FridaDevice(device));
198
+
199
+ gerror:
200
+ g_object_unref(options);
201
+ raise_rerror(NULL, _gerr);
202
+ return (Qnil);
203
+ }
204
+
205
+ GVL_FREE_PROXY_FUNC(remove_remote_device_sync, remove_remote_devices_proxy_args *args)
206
+ {
207
+ GError *gerr = NULL;
208
+
209
+ frida_device_manager_remove_remote_device_sync(args->device_manager, args->address, NULL, &gerr);
210
+ RETURN_GVL_FREE_RESULT(NULL);
211
+ }
212
+
213
+ /*
214
+ call-seq:
215
+ #remove_remote_device(address) -> nil
216
+ */
217
+ static VALUE DeviceManager_remove_remote_device(VALUE self, VALUE address)
218
+ {
219
+ GET_GOBJECT_DATA();
220
+ REQUIRE_GOBJECT_HANDLE();
221
+
222
+ if (!RB_TYPE_P(address, T_STRING)) {
223
+ raise_argerror("address should be a string.");
224
+ return (Qnil);
225
+ }
226
+ remove_remote_devices_proxy_args args = {
227
+ .device_manager = d->handle,
228
+ .address = StringValueCStr(address)
229
+ };
230
+ CALL_GVL_FREE_WITH_RET(void *dummy, remove_remote_device_sync, &args);
231
+ return (Qnil);
232
+
233
+ GERROR_BLOCK
234
+ }
235
+
236
+ /*
237
+ call-seq:
238
+ #new() -> DeviceManager
239
+ */
240
+ static VALUE DeviceManager_initialize(VALUE self)
241
+ {
242
+ GET_GOBJECT_DATA();
243
+ d->handle = frida_device_manager_new();
244
+ if (!d->handle)
245
+ return (raise_rerror("failed to retrieve a device manager.", NULL), Qnil);
246
+ d->destroy = DeviceManager_destroy;
247
+ return (self);
248
+ }
249
+
250
+ void define_DeviceManager()
251
+ {
252
+ cDeviceManager = rb_define_class_under(mCFrida, "DeviceManager", cGObject);
253
+
254
+ rb_define_method(cDeviceManager, "initialize", DeviceManager_initialize, 0);
255
+ rb_define_method(cDeviceManager, "enumerate_devices", DeviceManager_enumerate_devices, 0);
256
+ rb_define_method(cDeviceManager, "get_device_matching", DeviceManager_get_device_matching, 0);
257
+ rb_define_method(cDeviceManager, "add_remote_device", DeviceManager_add_remote_device, -1);
258
+ rb_define_method(cDeviceManager, "remove_remote_device", DeviceManager_remove_remote_device, 1);
259
+ rb_define_method(cDeviceManager, "close", DeviceManager_close, 0);
260
+ }
File without changes
File without changes
File without changes