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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/// C ABI wrapper header — bridges Ray C++ SDK templates to plain C functions.
///
/// The Ray C++ SDK uses heavy C++ templates (Put<T>, Task<F>, etc.) that have no
/// stable ABI. This header exposes a minimal C interface that the Rust FFI layer
/// can call. The C++ source (ray_c.cc) wraps `ray::internal::GetRayRuntime()` directly,
/// bypassing the template API.
///
/// IMPORTANT: Ray object IDs are binary strings that may contain null bytes.
/// All functions that return or accept IDs use `ray_bytes_t` (ptr + len)
/// instead of null-terminated `char*` to be binary-safe.
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/// Byte buffer: data pointer + length. Binary-safe.
typedef struct {
const char *data;
size_t len;
} ray_bytes_t;
// ─── Lifecycle ────────────────────────────────────────────────
/// Initialize Ray runtime.
/// `address` is "ip:port" of the head node (e.g. "192.168.42.141:6379").
/// Pass NULL or empty string for local mode.
/// `node_ip` is the IP address of this node as seen by the cluster.
/// Pass NULL to auto-detect.
/// `code_search_path` is a colon-separated list of directories or .so files
/// for the worker to search for remote functions. Pass NULL to skip.
/// `runtime_env_json` is a JSON string for runtime_env (e.g. {"pip": ["pkg"]}).
/// Pass NULL to skip.
/// `log_dir` is the directory for Ray logs. Pass NULL for default.
/// Returns 0 on success, -1 on failure.
int ray_init(const char *address, int local_mode, const char *node_ip,
const char *code_search_path,
const char *runtime_env_json,
const char *log_dir);
/// Returns true if ray::Init has been called.
bool ray_is_initialized(void);
/// Shutdown Ray runtime.
void ray_shutdown(void);
// ─── Object Store ─────────────────────────────────────────────
/// Put a serialized object into the object store.
/// `data` is msgpack-serialized bytes.
/// Returns a ray_bytes_t containing the binary object ID.
/// Caller must free with ray_free_bytes.
ray_bytes_t ray_put(const char *data, size_t len);
/// Get a single object from the object store.
/// `id_data`/`id_len` is the binary object ID.
/// `timeout_ms` is -1 for infinite wait.
/// Returns a ray_bytes_t containing the serialized object data.
/// On error, returns ray_bytes_t with data=NULL.
ray_bytes_t ray_get(const char *id_data, size_t id_len, int timeout_ms);
/// Wait for objects to be locally available.
/// `ids` is an array of ray_bytes_t (binary object IDs).
/// `count` is the number of IDs.
/// `num_objects` is the minimum number to wait for.
/// `timeout_ms` is -1 for infinite wait.
/// Returns a heap-allocated bool array (one per input ID).
/// Caller must free with ray_free_bools.
bool *ray_wait(const ray_bytes_t *ids, size_t count, int num_objects, int timeout_ms);
// ─── Task ─────────────────────────────────────────────────────
/// Call a remote task by function name.
/// `func_name` is a null-terminated C string (function names are ASCII).
/// `args` is an array of msgpack-serialized arguments.
/// `is_ref` is an array of booleans (same length as args). If is_ref[i] is true,
/// args[i] is treated as a binary ObjectRef ID (pass by reference).
/// Pass NULL to treat all args as values.
/// Returns a ray_bytes_t containing the binary object ID of the result.
/// On error, returns ray_bytes_t with data=NULL.
ray_bytes_t ray_task_call(const char *func_name,
const ray_bytes_t *args,
size_t arg_count,
const bool *is_ref);
/// Call a remote task with resource requirements.
/// `resources_json` is a JSON string like `{"CPU":1,"GPU":0.5}` or NULL.
ray_bytes_t ray_task_call_with_resources(const char *func_name,
const ray_bytes_t *args,
size_t arg_count,
const bool *is_ref,
const char *resources_json);
/// Call a Python remote function.
/// `module_name` and `function_name` are null-terminated C strings.
/// `args` are msgpack-serialized arguments (will be wrapped with xlang header).
/// `is_ref[i] = true` means args[i] is an ObjectRef ID (pass by reference).
ray_bytes_t ray_task_call_python(const char *module_name,
const char *function_name,
const ray_bytes_t *args,
size_t arg_count,
const bool *is_ref);
// ─── Actor ────────────────────────────────────────────────────
/// Create an actor by calling a factory function.
/// Returns a ray_bytes_t containing the binary actor ID.
ray_bytes_t ray_actor_create(const char *func_name,
const ray_bytes_t *args,
size_t arg_count);
/// Create an actor with resource requirements.
/// `resources_json` is a JSON string like `{"CPU":1,"GPU":1}` or NULL.
ray_bytes_t ray_actor_create_with_resources(const char *func_name,
const ray_bytes_t *args,
size_t arg_count,
const char *resources_json);
/// Create a Python actor.
/// `module_name` is the Python module, `class_name` is the Python class.
ray_bytes_t ray_actor_create_python(const char *module_name,
const char *class_name,
const ray_bytes_t *args,
size_t arg_count);
/// Call a method on an actor.
/// `actor_id_data`/`actor_id_len` is the binary actor ID.
/// Returns a ray_bytes_t containing the binary object ID of the result.
ray_bytes_t ray_actor_call(const char *actor_id_data, size_t actor_id_len,
const char *func_name,
const ray_bytes_t *args,
size_t arg_count);
/// Call a method on a Python actor.
/// `method_name` is the Python method name (without `self`).
/// `is_ref[i] = true` means args[i] is an ObjectRef ID (pass by reference).
ray_bytes_t ray_actor_call_python(const char *actor_id_data, size_t actor_id_len,
const char *method_name,
const ray_bytes_t *args,
size_t arg_count,
const bool *is_ref);
/// Kill an actor.
/// `actor_id_data`/`actor_id_len` is the binary actor ID.
void ray_actor_kill(const char *actor_id_data, size_t actor_id_len, bool no_restart);
// ─── Placement Group ──────────────────────────────────────────
/// Create a placement group.
/// `name` is a null-terminated string (can be NULL).
/// `bundles_json` is a JSON array of bundle objects.
/// `strategy` is 0=PACK, 1=SPREAD, 2=STRICT_PACK, 3=STRICT_SPREAD.
/// Returns a ray_bytes_t containing the group ID.
ray_bytes_t ray_placement_group_create(const char *name,
const char *bundles_json,
int strategy);
/// Remove a placement group by ID.
/// `group_id_data`/`group_id_len` is the binary group ID.
void ray_placement_group_remove(const char *group_id_data, size_t group_id_len);
// ─── Misc ─────────────────────────────────────────────────────
/// Returns true if the current actor was restarted.
bool ray_was_current_actor_restarted(void);
/// Get the namespace of this job.
/// Returns a ray_bytes_t containing the namespace string.
ray_bytes_t ray_get_namespace(void);
/// Get a named actor by name.
/// `name` is the actor name. `namespace` can be NULL for current namespace.
/// Returns a ray_bytes_t containing the binary actor ID, or data=NULL if not found.
ray_bytes_t ray_get_actor(const char *name, const char *ray_namespace);
/// Cancel a remote task by object ID.
/// `force_kill` kills the worker if true. `recursive` cancels dependent tasks.
/// Returns 0 on success, -1 on error.
int ray_cancel(const char *id_data, size_t id_len, bool force_kill, bool recursive);
/// Get multiple objects from the object store.
/// `ids` is an array of ray_bytes_t. `count` is the number of IDs.
/// `timeout_ms` is -1 for infinite wait.
/// Returns a heap-allocated array of ray_bytes_t (one per input ID).
/// On error for a specific ID, that element will have data=NULL.
/// Caller must free each element with ray_free_bytes, then free the array.
ray_bytes_t *ray_get_many(const ray_bytes_t *ids, size_t count, int timeout_ms);
/// Free an array returned by ray_get_many.
void ray_free_bytes_array(ray_bytes_t *array, size_t count);
// ─── Function Registration ────────────────────────────────────
/// Callback type for a Rust remote function.
/// Receives an array of msgpack-serialized argument buffers.
/// Returns a heap-allocated ray_bytes_t containing the msgpack-serialized result.
/// The caller (C wrapper) will free the returned data with free().
typedef ray_bytes_t (*ray_func_callback_t)(const ray_bytes_t *args, size_t arg_count);
/// Register a Rust function as a Ray remote task.
/// Must be called before ray_init (or at least before the first task call).
/// `func_name` is the name used with ray_task_call.
/// `callback` is the C callback that will be invoked when the task executes.
void ray_register_function(const char *func_name, ray_func_callback_t callback);
// ─── Actor Member Function Registration ───────────────────────
/// Callback type for a Rust actor member function.
/// `actor_ptr` is the raw pointer (uint64_t) stored by the factory.
/// `args` / `arg_count` are the msgpack-serialized arguments (without `self`).
/// Returns a heap-allocated ray_bytes_t containing the msgpack-serialized result.
typedef ray_bytes_t (*ray_member_callback_t)(uint64_t actor_ptr,
const ray_bytes_t *args,
size_t arg_count);
/// Register a Rust actor member function.
/// `func_name` is the name used with ray_actor_call.
/// `callback` is the C callback invoked when the actor method executes.
void ray_register_member_function(const char *func_name, ray_member_callback_t callback);
// ─── Async Get (CoreWorker::GetAsync + eventfd) ──────────────
/// Opaque handle for an async get request.
/// Internally holds an eventfd and a pending result buffer.
typedef struct ray_async_get ray_async_get_t;
/// Start an async get for an object.
/// Returns a heap-allocated ray_async_get_t, or NULL on error.
/// The caller must free it with ray_async_get_destroy.
ray_async_get_t *ray_async_get_start(const char *id_data, size_t id_len);
/// Get the eventfd file descriptor for polling.
/// Returns -1 on error.
int ray_async_get_fd(const ray_async_get_t *handle);
/// Check if the result is ready (non-blocking).
/// Returns 1 if ready, 0 if not, -1 on error.
int ray_async_get_is_ready(const ray_async_get_t *handle);
/// Get the result data (only valid if is_ready returns 1).
/// Returns a ray_bytes_t. On error, data=NULL.
ray_bytes_t ray_async_get_result(const ray_async_get_t *handle);
/// Destroy the handle and free resources.
void ray_async_get_destroy(ray_async_get_t *handle);
// ─── Memory Management ────────────────────────────────────────
/// Free a ray_bytes_t returned by any ray_* function.
void ray_free_bytes(ray_bytes_t *ptr);
/// Free a bool array returned by ray_wait.
void ray_free_bools(bool *ptr);
// ─── Error Handling ───────────────────────────────────────────
/// Get the last error message (thread-local).
/// Returns NULL if no error. The returned pointer is valid until the next
/// ray_* call on the same thread.
const char *ray_last_error(void);
/// Clear the last error message.
void ray_clear_error(void);
#ifdef __cplusplus
}
#endif