1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Frame profiling, the debug inspector and postponed jobs (`ruby/debug.h`).
use crate::rubysys::types::{c_int, c_long, c_uint, c_void, Value};
// typedef struct rb_debug_inspector_struct rb_debug_inspector_t;
#[repr(C)]
pub struct DebugInspector {
_private: [u8; 0],
}
// typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *dc, void *data);
pub type DebugInspectorFunction =
rutie_callback!(type fn(dc: *const DebugInspector, data: *mut c_void) -> Value);
// typedef void (*rb_postponed_job_func_t)(void *arg);
pub type PostponedJobFunction = rutie_callback!(type fn(arg: *mut c_void));
// typedef unsigned int rb_postponed_job_handle_t;
#[cfg(ruby_gte_3_3)]
pub type PostponedJobHandle = c_uint;
// #define POSTPONED_JOB_HANDLE_INVALID ((rb_postponed_job_handle_t)UINT_MAX)
#[cfg(ruby_gte_3_3)]
pub const POSTPONED_JOB_HANDLE_INVALID: PostponedJobHandle = PostponedJobHandle::MAX;
#[cfg_attr(rutie_dllimport, link(name = "rutie_ruby"))]
extern "C" {
// Fills `buff` with up to `limit` frames of the current thread's stack,
// from the `start`th (0 is the top), and `lines` (which may be NULL) with
// their line numbers. Returns the number of frames filled.
//
// The frames are opaque (an iseq or method entry): only the
// `rb_profile_frame_*` functions may be called on them. A block is
// reported as its method. Ruby 3.1 to 3.3 ignore `start`.
//
// int
// rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
pub fn rb_profile_frames(
start: c_int,
limit: c_int,
buff: *mut Value,
lines: *mut c_int,
) -> c_int;
// Like `rb_profile_frames`, for `thread`.
//
// int
// rb_profile_thread_frames(VALUE thread, int start, int limit, VALUE *buff, int *lines)
#[cfg(ruby_gte_3_3)]
pub fn rb_profile_thread_frames(
thread: Value,
start: c_int,
limit: c_int,
buff: *mut Value,
lines: *mut c_int,
) -> c_int;
// VALUE
// rb_profile_frame_path(VALUE frame)
pub fn rb_profile_frame_path(frame: Value) -> Value;
// VALUE
// rb_profile_frame_absolute_path(VALUE frame)
pub fn rb_profile_frame_absolute_path(frame: Value) -> Value;
// VALUE
// rb_profile_frame_label(VALUE frame)
pub fn rb_profile_frame_label(frame: Value) -> Value;
// VALUE
// rb_profile_frame_base_label(VALUE frame)
pub fn rb_profile_frame_base_label(frame: Value) -> Value;
// VALUE
// rb_profile_frame_full_label(VALUE frame)
pub fn rb_profile_frame_full_label(frame: Value) -> Value;
// VALUE
// rb_profile_frame_first_lineno(VALUE frame)
pub fn rb_profile_frame_first_lineno(frame: Value) -> Value;
// VALUE
// rb_profile_frame_classpath(VALUE frame)
pub fn rb_profile_frame_classpath(frame: Value) -> Value;
// VALUE
// rb_profile_frame_singleton_method_p(VALUE frame)
pub fn rb_profile_frame_singleton_method_p(frame: Value) -> Value;
// VALUE
// rb_profile_frame_method_name(VALUE frame)
pub fn rb_profile_frame_method_name(frame: Value) -> Value;
// VALUE
// rb_profile_frame_qualified_method_name(VALUE frame)
pub fn rb_profile_frame_qualified_method_name(frame: Value) -> Value;
// Calls `func` with a debug context for the current stack, which is only
// valid during the call, and returns what it returns.
//
// VALUE
// rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
pub fn rb_debug_inspector_open(func: DebugInspectorFunction, data: *mut c_void) -> Value;
// An `Array` of `Thread::Backtrace::Location`, one per frame.
//
// VALUE
// rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
pub fn rb_debug_inspector_backtrace_locations(dc: *const DebugInspector) -> Value;
// The `rb_debug_inspector_frame_*` functions raise an `ArgumentError` for
// an `index` out of the range of the backtrace locations.
//
// VALUE
// rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index)
pub fn rb_debug_inspector_frame_self_get(dc: *const DebugInspector, index: c_long) -> Value;
// VALUE
// rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index)
pub fn rb_debug_inspector_frame_class_get(dc: *const DebugInspector, index: c_long) -> Value;
// VALUE
// rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index)
pub fn rb_debug_inspector_frame_binding_get(dc: *const DebugInspector, index: c_long) -> Value;
// `Qnil` for a frame not in Ruby.
//
// VALUE
// rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index)
pub fn rb_debug_inspector_frame_iseq_get(dc: *const DebugInspector, index: c_long) -> Value;
// The stack depth of the frame (an `Integer`), counting the special
// frames the inspector skips.
//
// VALUE
// rb_debug_inspector_frame_depth(const rb_debug_inspector_t *dc, long index)
pub fn rb_debug_inspector_frame_depth(dc: *const DebugInspector, index: c_long) -> Value;
// The stack depth of the current frame (an `Integer`).
//
// VALUE
// rb_debug_inspector_current_depth(void)
pub fn rb_debug_inspector_current_depth() -> Value;
// Registers `func` in the postponed job table (32 entries, never freed)
// and returns its handle, or `POSTPONED_JOB_HANDLE_INVALID` when the table
// is full. Registering the same `func` again replaces its `data` and
// returns the same handle. `flags` is unused.
//
// rb_postponed_job_handle_t
// rb_postponed_job_preregister(unsigned int flags, rb_postponed_job_func_t func, void *data)
#[cfg(ruby_gte_3_3)]
pub fn rb_postponed_job_preregister(
flags: c_uint,
func: PostponedJobFunction,
data: *mut c_void,
) -> PostponedJobHandle;
// Makes Ruby run the job the next time it checks for interrupts, with
// the GVL held. Async signal safe; callable from any thread.
//
// void
// rb_postponed_job_trigger(rb_postponed_job_handle_t h)
#[cfg(ruby_gte_3_3)]
pub fn rb_postponed_job_trigger(handle: PostponedJobHandle);
// Deprecated in Ruby 3.3 for `rb_postponed_job_preregister` and
// `rb_postponed_job_trigger`. Returns 0 when the job could not be
// registered.
//
// int
// rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void *data)
pub fn rb_postponed_job_register(
flags: c_uint,
func: PostponedJobFunction,
data: *mut c_void,
) -> c_int;
// Like `rb_postponed_job_register`, but does nothing when `func` is
// already registered. Deprecated in Ruby 3.3.
//
// int
// rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func,
// void *data)
pub fn rb_postponed_job_register_one(
flags: c_uint,
func: PostponedJobFunction,
data: *mut c_void,
) -> c_int;
}