1/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#ifndef TENSORFLOW_C_C_API_H_
17#define TENSORFLOW_C_C_API_H_
18
19#include <stddef.h>
20#include <stdint.h>
21
22#include "tensorflow/c/tf_attrtype.h"
23#include "tensorflow/c/tf_buffer.h"
24#include "tensorflow/c/tf_datatype.h"
25#include "tensorflow/c/tf_status.h"
26#include "tensorflow/c/tf_tensor.h"
27#include "tensorflow/c/tf_tstring.h"
28
29// --------------------------------------------------------------------------
30// C API for TensorFlow.
31//
32// The API leans towards simplicity and uniformity instead of convenience
33// since most usage will be by language specific wrappers.
34//
35// Conventions:
36// * We use the prefix TF_ for everything in the API.
37// * Objects are always passed around as pointers to opaque structs
38// and these structs are allocated/deallocated via the API.
39// * TF_Status holds error information. It is an object type
40// and therefore is passed around as a pointer to an opaque
41// struct as mentioned above.
42// * Every call that has a TF_Status* argument clears it on success
43// and fills it with error info on failure.
44// * unsigned char is used for booleans (instead of the 'bool' type).
45// In C++ bool is a keyword while in C99 bool is a macro defined
46// in stdbool.h. It is possible for the two to be inconsistent.
47// For example, neither the C99 nor the C++11 standard force a byte
48// size on the bool type, so the macro defined in stdbool.h could
49// be inconsistent with the bool keyword in C++. Thus, the use
50// of stdbool.h is avoided and unsigned char is used instead.
51// * size_t is used to represent byte sizes of objects that are
52// materialized in the address space of the calling process.
53// * int is used as an index into arrays.
54// * Deletion functions are safe to call on nullptr.
55//
56// Questions left to address:
57// * Might at some point need a way for callers to provide their own Env.
58// * Maybe add TF_TensorShape that encapsulates dimension info.
59//
60// Design decisions made:
61// * Backing store for tensor memory has an associated deallocation
62// function. This deallocation function will point to client code
63// for tensors populated by the client. So the client can do things
64// like shadowing a numpy array.
65// * We do not provide TF_OK since it is not strictly necessary and we
66// are not optimizing for convenience.
67// * We make assumption that one session has one graph. This should be
68// fine since we have the ability to run sub-graphs.
69// * We could allow NULL for some arguments (e.g., NULL options arg).
70// However since convenience is not a primary goal, we don't do this.
71// * Devices are not in this API. Instead, they are created/used internally
72// and the API just provides high level controls over the number of
73// devices of each type.
74
75// Macro to control visibility of exported symbols in the shared library (.so,
76// .dylib, .dll).
77// This duplicates the TF_EXPORT macro definition in
78// tensorflow/core/platform/macros.h in order to keep this .h file independent
79// of any other includes.
80#ifdef SWIG
81#define TF_CAPI_EXPORT
82#else
83#if defined(_WIN32)
84#ifdef TF_COMPILE_LIBRARY
85#define TF_CAPI_EXPORT __declspec(dllexport)
86#else
87#define TF_CAPI_EXPORT __declspec(dllimport)
88#endif // TF_COMPILE_LIBRARY
89#else
90#define TF_CAPI_EXPORT __attribute__((visibility("default")))
91#endif // _WIN32
92#endif // SWIG
93
94#ifdef __cplusplus
95extern "C" {
96#endif
97
98// --------------------------------------------------------------------------
99// TF_Version returns a string describing version information of the
100// TensorFlow library. TensorFlow uses semantic versioning.
101TF_CAPI_EXPORT extern const char* TF_Version(void);
102
103// Parsing a serialized TensorProto into a TF_Tensor.
104TF_CAPI_EXPORT extern void TF_TensorFromProto(const TF_Buffer* from,
105 TF_Tensor* to, TF_Status* status);
106
107// --------------------------------------------------------------------------
108// Used to return strings across the C API. The caller does not take ownership
109// of the underlying data pointer and is not responsible for freeing it.
110typedef struct TF_StringView {
111 const char* data;
112 size_t len;
113} TF_StringView;
114
115// --------------------------------------------------------------------------
116// TF_SessionOptions holds options that can be passed during session creation.
117typedef struct TF_SessionOptions TF_SessionOptions;
118
119// Return a new options object.
120TF_CAPI_EXPORT extern TF_SessionOptions* TF_NewSessionOptions(void);
121
122// Set the target in TF_SessionOptions.options.
123// target can be empty, a single entry, or a comma separated list of entries.
124// Each entry is in one of the following formats :
125// "local"
126// ip:port
127// host:port
128TF_CAPI_EXPORT extern void TF_SetTarget(TF_SessionOptions* options,
129 const char* target);
130
131// Set the config in TF_SessionOptions.options.
132// config should be a serialized tensorflow.ConfigProto proto.
133// If config was not parsed successfully as a ConfigProto, record the
134// error information in *status.
135TF_CAPI_EXPORT extern void TF_SetConfig(TF_SessionOptions* options,
136 const void* proto, size_t proto_len,
137 TF_Status* status);
138
139// Destroy an options object.
140TF_CAPI_EXPORT extern void TF_DeleteSessionOptions(TF_SessionOptions*);
141
142// TODO(jeff,sanjay):
143// - export functions to set Config fields
144
145// --------------------------------------------------------------------------
146// The new graph construction API, still under development.
147
148// Represents a computation graph. Graphs may be shared between sessions.
149// Graphs are thread-safe when used as directed below.
150typedef struct TF_Graph TF_Graph;
151
152// Return a new graph object.
153TF_CAPI_EXPORT extern TF_Graph* TF_NewGraph(void);
154
155// Destroy an options object. Graph will be deleted once no more
156// TFSession's are referencing it.
157TF_CAPI_EXPORT extern void TF_DeleteGraph(TF_Graph*);
158
159// Operation being built. The underlying graph must outlive this.
160typedef struct TF_OperationDescription TF_OperationDescription;
161
162// Operation that has been added to the graph. Valid until the graph is
163// deleted -- in particular adding a new operation to the graph does not
164// invalidate old TF_Operation* pointers.
165typedef struct TF_Operation TF_Operation;
166
167// Represents a specific input of an operation.
168typedef struct TF_Input {
169 TF_Operation* oper;
170 int index; // The index of the input within oper.
171} TF_Input;
172
173// Represents a specific output of an operation.
174typedef struct TF_Output {
175 TF_Operation* oper;
176 int index; // The index of the output within oper.
177} TF_Output;
178
179// TF_Function is a grouping of operations with defined inputs and outputs.
180// Once created and added to graphs, functions can be invoked by creating an
181// operation whose operation type matches the function name.
182typedef struct TF_Function TF_Function;
183
184// Function definition options. TODO(iga): Define and implement
185typedef struct TF_FunctionOptions TF_FunctionOptions;
186
187// Sets the shape of the Tensor referenced by `output` in `graph` to
188// the shape described by `dims` and `num_dims`.
189//
190// If the number of dimensions is unknown, `num_dims` must be set to
191// -1 and `dims` can be null. If a dimension is unknown, the
192// corresponding entry in the `dims` array must be -1.
193//
194// This does not overwrite the existing shape associated with `output`,
195// but merges the input shape with the existing shape. For example,
196// setting a shape of [-1, 2] with an existing shape [2, -1] would set
197// a final shape of [2, 2] based on shape merging semantics.
198//
199// Returns an error into `status` if:
200// * `output` is not in `graph`.
201// * An invalid shape is being set (e.g., the shape being set
202// is incompatible with the existing shape).
203TF_CAPI_EXPORT extern void TF_GraphSetTensorShape(TF_Graph* graph,
204 TF_Output output,
205 const int64_t* dims,
206 const int num_dims,
207 TF_Status* status);
208
209// Returns the number of dimensions of the Tensor referenced by `output`
210// in `graph`.
211//
212// If the number of dimensions in the shape is unknown, returns -1.
213//
214// Returns an error into `status` if:
215// * `output` is not in `graph`.
216TF_CAPI_EXPORT extern int TF_GraphGetTensorNumDims(TF_Graph* graph,
217 TF_Output output,
218 TF_Status* status);
219
220// Returns the shape of the Tensor referenced by `output` in `graph`
221// into `dims`. `dims` must be an array large enough to hold `num_dims`
222// entries (e.g., the return value of TF_GraphGetTensorNumDims).
223//
224// If the number of dimensions in the shape is unknown or the shape is
225// a scalar, `dims` will remain untouched. Otherwise, each element of
226// `dims` will be set corresponding to the size of the dimension. An
227// unknown dimension is represented by `-1`.
228//
229// Returns an error into `status` if:
230// * `output` is not in `graph`.
231// * `num_dims` does not match the actual number of dimensions.
232TF_CAPI_EXPORT extern void TF_GraphGetTensorShape(TF_Graph* graph,
233 TF_Output output,
234 int64_t* dims, int num_dims,
235 TF_Status* status);
236
237// Creates a new operation - see `TF_NewOperation` for more details.
238//
239// The lock for `graph` must be held when calling this function.
240//
241// Unless implementing advanced behavior, like custom gradient functions, you
242// most likely need to call `TF_NewOperation` instead.
243TF_CAPI_EXPORT extern TF_OperationDescription* TF_NewOperationLocked(
244 TF_Graph* graph, const char* op_type, const char* oper_name);
245
246// Operation will only be added to *graph when TF_FinishOperation() is
247// called (assuming TF_FinishOperation() does not return an error).
248// *graph must not be deleted until after TF_FinishOperation() is
249// called.
250TF_CAPI_EXPORT extern TF_OperationDescription* TF_NewOperation(
251 TF_Graph* graph, const char* op_type, const char* oper_name);
252
253// Specify the device for `desc`. Defaults to empty, meaning unconstrained.
254TF_CAPI_EXPORT extern void TF_SetDevice(TF_OperationDescription* desc,
255 const char* device);
256
257// The calls to TF_AddInput and TF_AddInputList must match (in number,
258// order, and type) the op declaration. For example, the "Concat" op
259// has registration:
260// REGISTER_OP("Concat")
261// .Input("concat_dim: int32")
262// .Input("values: N * T")
263// .Output("output: T")
264// .Attr("N: int >= 2")
265// .Attr("T: type");
266// that defines two inputs, "concat_dim" and "values" (in that order).
267// You must use TF_AddInput() for the first input (since it takes a
268// single tensor), and TF_AddInputList() for the second input (since
269// it takes a list, even if you were to pass a list with a single
270// tensor), as in:
271// TF_OperationDescription* desc = TF_NewOperation(graph, "Concat", "c");
272// TF_Output concat_dim_input = {...};
273// TF_AddInput(desc, concat_dim_input);
274// TF_Output values_inputs[5] = {{...}, ..., {...}};
275// TF_AddInputList(desc, values_inputs, 5);
276
277// For inputs that take a single tensor.
278TF_CAPI_EXPORT extern void TF_AddInput(TF_OperationDescription* desc,
279 TF_Output input);
280
281// For inputs that take a list of tensors.
282// inputs must point to TF_Output[num_inputs].
283TF_CAPI_EXPORT extern void TF_AddInputList(TF_OperationDescription* desc,
284 const TF_Output* inputs,
285 int num_inputs);
286
287// Call once per control input to `desc`.
288TF_CAPI_EXPORT extern void TF_AddControlInput(TF_OperationDescription* desc,
289 TF_Operation* input);
290
291// Request that `desc` be co-located on the device where `op`
292// is placed.
293//
294// Use of this is discouraged since the implementation of device placement is
295// subject to change. Primarily intended for internal libraries
296TF_CAPI_EXPORT extern void TF_ColocateWith(TF_OperationDescription* desc,
297 TF_Operation* op);
298
299// Call some TF_SetAttr*() function for every attr that is not
300// inferred from an input and doesn't have a default value you wish to
301// keep.
302
303// `value` must point to a string of length `length` bytes.
304TF_CAPI_EXPORT extern void TF_SetAttrString(TF_OperationDescription* desc,
305 const char* attr_name,
306 const void* value, size_t length);
307// `values` and `lengths` each must have lengths `num_values`.
308// `values[i]` must point to a string of length `lengths[i]` bytes.
309TF_CAPI_EXPORT extern void TF_SetAttrStringList(TF_OperationDescription* desc,
310 const char* attr_name,
311 const void* const* values,
312 const size_t* lengths,
313 int num_values);
314TF_CAPI_EXPORT extern void TF_SetAttrInt(TF_OperationDescription* desc,
315 const char* attr_name, int64_t value);
316TF_CAPI_EXPORT extern void TF_SetAttrIntList(TF_OperationDescription* desc,
317 const char* attr_name,
318 const int64_t* values,
319 int num_values);
320TF_CAPI_EXPORT extern void TF_SetAttrFloat(TF_OperationDescription* desc,
321 const char* attr_name, float value);
322TF_CAPI_EXPORT extern void TF_SetAttrFloatList(TF_OperationDescription* desc,
323 const char* attr_name,
324 const float* values,
325 int num_values);
326TF_CAPI_EXPORT extern void TF_SetAttrBool(TF_OperationDescription* desc,
327 const char* attr_name,
328 unsigned char value);
329TF_CAPI_EXPORT extern void TF_SetAttrBoolList(TF_OperationDescription* desc,
330 const char* attr_name,
331 const unsigned char* values,
332 int num_values);
333TF_CAPI_EXPORT extern void TF_SetAttrType(TF_OperationDescription* desc,
334 const char* attr_name,
335 TF_DataType value);
336TF_CAPI_EXPORT extern void TF_SetAttrTypeList(TF_OperationDescription* desc,
337 const char* attr_name,
338 const TF_DataType* values,
339 int num_values);
340TF_CAPI_EXPORT extern void TF_SetAttrPlaceholder(TF_OperationDescription* desc,
341 const char* attr_name,
342 const char* placeholder);
343
344// Set a 'func' attribute to the specified name.
345// `value` must point to a string of length `length` bytes.
346TF_CAPI_EXPORT extern void TF_SetAttrFuncName(TF_OperationDescription* desc,
347 const char* attr_name,
348 const char* value, size_t length);
349
350// Set `num_dims` to -1 to represent "unknown rank". Otherwise,
351// `dims` points to an array of length `num_dims`. `dims[i]` must be
352// >= -1, with -1 meaning "unknown dimension".
353TF_CAPI_EXPORT extern void TF_SetAttrShape(TF_OperationDescription* desc,
354 const char* attr_name,
355 const int64_t* dims, int num_dims);
356// `dims` and `num_dims` must point to arrays of length `num_shapes`.
357// Set `num_dims[i]` to -1 to represent "unknown rank". Otherwise,
358// `dims[i]` points to an array of length `num_dims[i]`. `dims[i][j]`
359// must be >= -1, with -1 meaning "unknown dimension".
360TF_CAPI_EXPORT extern void TF_SetAttrShapeList(TF_OperationDescription* desc,
361 const char* attr_name,
362 const int64_t* const* dims,
363 const int* num_dims,
364 int num_shapes);
365// `proto` must point to an array of `proto_len` bytes representing a
366// binary-serialized TensorShapeProto.
367TF_CAPI_EXPORT extern void TF_SetAttrTensorShapeProto(
368 TF_OperationDescription* desc, const char* attr_name, const void* proto,
369 size_t proto_len, TF_Status* status);
370// `protos` and `proto_lens` must point to arrays of length `num_shapes`.
371// `protos[i]` must point to an array of `proto_lens[i]` bytes
372// representing a binary-serialized TensorShapeProto.
373TF_CAPI_EXPORT extern void TF_SetAttrTensorShapeProtoList(
374 TF_OperationDescription* desc, const char* attr_name,
375 const void* const* protos, const size_t* proto_lens, int num_shapes,
376 TF_Status* status);
377
378TF_CAPI_EXPORT extern void TF_SetAttrTensor(TF_OperationDescription* desc,
379 const char* attr_name,
380 TF_Tensor* value,
381 TF_Status* status);
382TF_CAPI_EXPORT extern void TF_SetAttrTensorList(TF_OperationDescription* desc,
383 const char* attr_name,
384 TF_Tensor* const* values,
385 int num_values,
386 TF_Status* status);
387
388// `proto` should point to a sequence of bytes of length `proto_len`
389// representing a binary serialization of an AttrValue protocol
390// buffer.
391TF_CAPI_EXPORT extern void TF_SetAttrValueProto(TF_OperationDescription* desc,
392 const char* attr_name,
393 const void* proto,
394 size_t proto_len,
395 TF_Status* status);
396
397// Adds this operation to the graph - see `TF_FinishOperation` for more details.
398//
399// The lock for `graph` must be held when calling this function.
400//
401// Unless implementing advanced behavior, like custom gradient functions, you
402// most likely need to call `TF_FinishOperation` instead.
403TF_CAPI_EXPORT extern TF_Operation* TF_FinishOperationLocked(
404 TF_OperationDescription* desc, TF_Status* status);
405
406// If this function succeeds:
407// * *status is set to an OK value,
408// * a TF_Operation is added to the graph,
409// * a non-null value pointing to the added operation is returned --
410// this value is valid until the underlying graph is deleted.
411// Otherwise:
412// * *status is set to a non-OK value,
413// * the graph is not modified,
414// * a null value is returned.
415// In either case, it deletes `desc`.
416TF_CAPI_EXPORT extern TF_Operation* TF_FinishOperation(
417 TF_OperationDescription* desc, TF_Status* status);
418
419// TF_Operation functions. Operations are immutable once created, so
420// these are all query functions.
421
422TF_CAPI_EXPORT extern const char* TF_OperationName(TF_Operation* oper);
423TF_CAPI_EXPORT extern const char* TF_OperationOpType(TF_Operation* oper);
424TF_CAPI_EXPORT extern const char* TF_OperationDevice(TF_Operation* oper);
425
426TF_CAPI_EXPORT extern int TF_OperationNumOutputs(TF_Operation* oper);
427TF_CAPI_EXPORT extern TF_DataType TF_OperationOutputType(TF_Output oper_out);
428TF_CAPI_EXPORT extern int TF_OperationOutputListLength(TF_Operation* oper,
429 const char* arg_name,
430 TF_Status* status);
431
432TF_CAPI_EXPORT extern int TF_OperationNumInputs(TF_Operation* oper);
433TF_CAPI_EXPORT extern TF_DataType TF_OperationInputType(TF_Input oper_in);
434TF_CAPI_EXPORT extern int TF_OperationInputListLength(TF_Operation* oper,
435 const char* arg_name,
436 TF_Status* status);
437
438// In this code:
439// TF_Output producer = TF_OperationInput(consumer);
440// There is an edge from producer.oper's output (given by
441// producer.index) to consumer.oper's input (given by consumer.index).
442TF_CAPI_EXPORT extern TF_Output TF_OperationInput(TF_Input oper_in);
443
444// Get list of all inputs of a specific operation. `inputs` must point to
445// an array of length at least `max_inputs` (ideally set to
446// TF_OperationNumInputs(oper)). Beware that a concurrent
447// modification of the graph can increase the number of inputs of
448// an operation.
449TF_CAPI_EXPORT extern void TF_OperationAllInputs(TF_Operation* oper,
450 TF_Output* inputs,
451 int max_inputs);
452
453// Get the number of current consumers of a specific output of an
454// operation. Note that this number can change when new operations
455// are added to the graph.
456TF_CAPI_EXPORT extern int TF_OperationOutputNumConsumers(TF_Output oper_out);
457
458// Get list of all current consumers of a specific output of an
459// operation. `consumers` must point to an array of length at least
460// `max_consumers` (ideally set to
461// TF_OperationOutputNumConsumers(oper_out)). Beware that a concurrent
462// modification of the graph can increase the number of consumers of
463// an operation. Returns the number of output consumers (should match
464// TF_OperationOutputNumConsumers(oper_out)).
465TF_CAPI_EXPORT extern int TF_OperationOutputConsumers(TF_Output oper_out,
466 TF_Input* consumers,
467 int max_consumers);
468
469// Get the number of control inputs to an operation.
470TF_CAPI_EXPORT extern int TF_OperationNumControlInputs(TF_Operation* oper);
471
472// Get list of all control inputs to an operation. `control_inputs` must
473// point to an array of length `max_control_inputs` (ideally set to
474// TF_OperationNumControlInputs(oper)). Returns the number of control
475// inputs (should match TF_OperationNumControlInputs(oper)).
476TF_CAPI_EXPORT extern int TF_OperationGetControlInputs(
477 TF_Operation* oper, TF_Operation** control_inputs, int max_control_inputs);
478
479// Get the number of operations that have `*oper` as a control input.
480// Note that this number can change when new operations are added to
481// the graph.
482TF_CAPI_EXPORT extern int TF_OperationNumControlOutputs(TF_Operation* oper);
483
484// Get the list of operations that have `*oper` as a control input.
485// `control_outputs` must point to an array of length at least
486// `max_control_outputs` (ideally set to
487// TF_OperationNumControlOutputs(oper)). Beware that a concurrent
488// modification of the graph can increase the number of control
489// outputs. Returns the number of control outputs (should match
490// TF_OperationNumControlOutputs(oper)).
491TF_CAPI_EXPORT extern int TF_OperationGetControlOutputs(
492 TF_Operation* oper, TF_Operation** control_outputs,
493 int max_control_outputs);
494
495// TF_AttrMetadata describes the value of an attribute on an operation.
496typedef struct TF_AttrMetadata {
497 // A boolean: 1 if the attribute value is a list, 0 otherwise.
498 unsigned char is_list;
499
500 // Length of the list if is_list is true. Undefined otherwise.
501 int64_t list_size;
502
503 // Type of elements of the list if is_list != 0.
504 // Type of the single value stored in the attribute if is_list == 0.
505 TF_AttrType type;
506
507 // Total size the attribute value.
508 // The units of total_size depend on is_list and type.
509 // (1) If type == TF_ATTR_STRING and is_list == 0
510 // then total_size is the byte size of the string
511 // valued attribute.
512 // (2) If type == TF_ATTR_STRING and is_list == 1
513 // then total_size is the cumulative byte size
514 // of all the strings in the list.
515 // (3) If type == TF_ATTR_SHAPE and is_list == 0
516 // then total_size is the number of dimensions
517 // of the shape valued attribute, or -1
518 // if its rank is unknown.
519 // (4) If type == TF_ATTR_SHAPE and is_list == 1
520 // then total_size is the cumulative number
521 // of dimensions of all shapes in the list.
522 // (5) Otherwise, total_size is undefined.
523 int64_t total_size;
524} TF_AttrMetadata;
525
526// Returns metadata about the value of the attribute `attr_name` of `oper`.
527TF_CAPI_EXPORT extern TF_AttrMetadata TF_OperationGetAttrMetadata(
528 TF_Operation* oper, const char* attr_name, TF_Status* status);
529
530// Fills in `value` with the value of the attribute `attr_name`. `value` must
531// point to an array of length at least `max_length` (ideally set to
532// TF_AttrMetadata.total_size from TF_OperationGetAttrMetadata(oper,
533// attr_name)).
534TF_CAPI_EXPORT extern void TF_OperationGetAttrString(TF_Operation* oper,
535 const char* attr_name,
536 void* value,
537 size_t max_length,
538 TF_Status* status);
539
540// Get the list of strings in the value of the attribute `attr_name`. Fills in
541// `values` and `lengths`, each of which must point to an array of length at
542// least `max_values`.
543//
544// The elements of values will point to addresses in `storage` which must be at
545// least `storage_size` bytes in length. Ideally, max_values would be set to
546// TF_AttrMetadata.list_size and `storage` would be at least
547// TF_AttrMetadata.total_size, obtained from TF_OperationGetAttrMetadata(oper,
548// attr_name).
549//
550// Fails if storage_size is too small to hold the requested number of strings.
551TF_CAPI_EXPORT extern void TF_OperationGetAttrStringList(
552 TF_Operation* oper, const char* attr_name, void** values, size_t* lengths,
553 int max_values, void* storage, size_t storage_size, TF_Status* status);
554
555TF_CAPI_EXPORT extern void TF_OperationGetAttrInt(TF_Operation* oper,
556 const char* attr_name,
557 int64_t* value,
558 TF_Status* status);
559
560// Fills in `values` with the value of the attribute `attr_name` of `oper`.
561// `values` must point to an array of length at least `max_values` (ideally set
562// TF_AttrMetadata.list_size from TF_OperationGetAttrMetadata(oper,
563// attr_name)).
564TF_CAPI_EXPORT extern void TF_OperationGetAttrIntList(TF_Operation* oper,
565 const char* attr_name,
566 int64_t* values,
567 int max_values,
568 TF_Status* status);
569
570TF_CAPI_EXPORT extern void TF_OperationGetAttrFloat(TF_Operation* oper,
571 const char* attr_name,
572 float* value,
573 TF_Status* status);
574
575// Fills in `values` with the value of the attribute `attr_name` of `oper`.
576// `values` must point to an array of length at least `max_values` (ideally set
577// to TF_AttrMetadata.list_size from TF_OperationGetAttrMetadata(oper,
578// attr_name)).
579TF_CAPI_EXPORT extern void TF_OperationGetAttrFloatList(TF_Operation* oper,
580 const char* attr_name,
581 float* values,
582 int max_values,
583 TF_Status* status);
584
585TF_CAPI_EXPORT extern void TF_OperationGetAttrBool(TF_Operation* oper,
586 const char* attr_name,
587 unsigned char* value,
588 TF_Status* status);
589
590// Fills in `values` with the value of the attribute `attr_name` of `oper`.
591// `values` must point to an array of length at least `max_values` (ideally set
592// to TF_AttrMetadata.list_size from TF_OperationGetAttrMetadata(oper,
593// attr_name)).
594TF_CAPI_EXPORT extern void TF_OperationGetAttrBoolList(TF_Operation* oper,
595 const char* attr_name,
596 unsigned char* values,
597 int max_values,
598 TF_Status* status);
599
600TF_CAPI_EXPORT extern void TF_OperationGetAttrType(TF_Operation* oper,
601 const char* attr_name,
602 TF_DataType* value,
603 TF_Status* status);
604
605// Fills in `values` with the value of the attribute `attr_name` of `oper`.
606// `values` must point to an array of length at least `max_values` (ideally set
607// to TF_AttrMetadata.list_size from TF_OperationGetAttrMetadata(oper,
608// attr_name)).
609TF_CAPI_EXPORT extern void TF_OperationGetAttrTypeList(TF_Operation* oper,
610 const char* attr_name,
611 TF_DataType* values,
612 int max_values,
613 TF_Status* status);
614
615// Fills in `value` with the value of the attribute `attr_name` of `oper`.
616// `values` must point to an array of length at least `num_dims` (ideally set to
617// TF_Attr_Meta.size from TF_OperationGetAttrMetadata(oper, attr_name)).
618TF_CAPI_EXPORT extern void TF_OperationGetAttrShape(TF_Operation* oper,
619 const char* attr_name,
620 int64_t* value,
621 int num_dims,
622 TF_Status* status);
623
624// Fills in `dims` with the list of shapes in the attribute `attr_name` of
625// `oper` and `num_dims` with the corresponding number of dimensions. On return,
626// for every i where `num_dims[i]` > 0, `dims[i]` will be an array of
627// `num_dims[i]` elements. A value of -1 for `num_dims[i]` indicates that the
628// i-th shape in the list is unknown.
629//
630// The elements of `dims` will point to addresses in `storage` which must be
631// large enough to hold at least `storage_size` int64_ts. Ideally, `num_shapes`
632// would be set to TF_AttrMetadata.list_size and `storage_size` would be set to
633// TF_AttrMetadata.total_size from TF_OperationGetAttrMetadata(oper,
634// attr_name).
635//
636// Fails if storage_size is insufficient to hold the requested shapes.
637TF_CAPI_EXPORT extern void TF_OperationGetAttrShapeList(
638 TF_Operation* oper, const char* attr_name, int64_t** dims, int* num_dims,
639 int num_shapes, int64_t* storage, int storage_size, TF_Status* status);
640
641// Sets `value` to the binary-serialized TensorShapeProto of the value of
642// `attr_name` attribute of `oper`.
643TF_CAPI_EXPORT extern void TF_OperationGetAttrTensorShapeProto(
644 TF_Operation* oper, const char* attr_name, TF_Buffer* value,
645 TF_Status* status);
646
647// Fills in `values` with binary-serialized TensorShapeProto values of the
648// attribute `attr_name` of `oper`. `values` must point to an array of length at
649// least `num_values` (ideally set to TF_AttrMetadata.list_size from
650// TF_OperationGetAttrMetadata(oper, attr_name)).
651TF_CAPI_EXPORT extern void TF_OperationGetAttrTensorShapeProtoList(
652 TF_Operation* oper, const char* attr_name, TF_Buffer** values,
653 int max_values, TF_Status* status);
654
655// Gets the TF_Tensor valued attribute of `attr_name` of `oper`.
656//
657// Allocates a new TF_Tensor which the caller is expected to take
658// ownership of (and can deallocate using TF_DeleteTensor).
659TF_CAPI_EXPORT extern void TF_OperationGetAttrTensor(TF_Operation* oper,
660 const char* attr_name,
661 TF_Tensor** value,
662 TF_Status* status);
663
664// Fills in `values` with the TF_Tensor values of the attribute `attr_name` of
665// `oper`. `values` must point to an array of TF_Tensor* of length at least
666// `max_values` (ideally set to TF_AttrMetadata.list_size from
667// TF_OperationGetAttrMetadata(oper, attr_name)).
668//
669// The caller takes ownership of all the non-null TF_Tensor* entries in `values`
670// (which can be deleted using TF_DeleteTensor(values[i])).
671TF_CAPI_EXPORT extern void TF_OperationGetAttrTensorList(TF_Operation* oper,
672 const char* attr_name,
673 TF_Tensor** values,
674 int max_values,
675 TF_Status* status);
676
677// Sets `output_attr_value` to the binary-serialized AttrValue proto
678// representation of the value of the `attr_name` attr of `oper`.
679TF_CAPI_EXPORT extern void TF_OperationGetAttrValueProto(
680 TF_Operation* oper, const char* attr_name, TF_Buffer* output_attr_value,
681 TF_Status* status);
682
683// Get the number of attributes the operation has.
684TF_CAPI_EXPORT extern int TF_OperationGetNumAttrs(TF_Operation* oper);
685
686// Get the length of the name of the ith attribute, or -1 if there is not an
687// ith attribute.
688TF_CAPI_EXPORT extern int TF_OperationGetAttrNameLength(TF_Operation* oper,
689 int i);
690
691// Get the name of the ith attribute. output should have the size of
692// TF_OperationGetAttrNameLength(oper, i).
693TF_CAPI_EXPORT extern void TF_OperationGetAttrName(TF_Operation* oper, int i,
694 char* output,
695 TF_Status* status);
696
697// Returns the operation in the graph with `oper_name`. Returns nullptr if
698// no operation found.
699TF_CAPI_EXPORT extern TF_Operation* TF_GraphOperationByName(
700 TF_Graph* graph, const char* oper_name);
701
702// Iterate through the operations of a graph. To use:
703// size_t pos = 0;
704// TF_Operation* oper;
705// while ((oper = TF_GraphNextOperation(graph, &pos)) != nullptr) {
706// DoSomethingWithOperation(oper);
707// }
708TF_CAPI_EXPORT extern TF_Operation* TF_GraphNextOperation(TF_Graph* graph,
709 size_t* pos);
710
711// Write out a serialized representation of `graph` (as a GraphDef protocol
712// message) to `output_graph_def` (allocated by TF_NewBuffer()).
713// `output_graph_def`'s underlying buffer will be freed when TF_DeleteBuffer()
714// is called.
715//
716// May fail on very large graphs in the future.
717TF_CAPI_EXPORT extern void TF_GraphToGraphDef(TF_Graph* graph,
718 TF_Buffer* output_graph_def,
719 TF_Status* status);
720
721// Returns the serialized OpDef proto with name `op_name`, or a bad status if no
722// such op exists. This can return OpDefs of functions copied into the graph.
723TF_CAPI_EXPORT extern void TF_GraphGetOpDef(TF_Graph* graph,
724 const char* op_name,
725 TF_Buffer* output_op_def,
726 TF_Status* status);
727
728// Returns the serialized VersionDef proto for this graph.
729TF_CAPI_EXPORT extern void TF_GraphVersions(TF_Graph* graph,
730 TF_Buffer* output_version_def,
731 TF_Status* status);
732
733// TF_ImportGraphDefOptions holds options that can be passed to
734// TF_GraphImportGraphDef.
735typedef struct TF_ImportGraphDefOptions TF_ImportGraphDefOptions;
736
737TF_CAPI_EXPORT extern TF_ImportGraphDefOptions* TF_NewImportGraphDefOptions(
738 void);
739TF_CAPI_EXPORT extern void TF_DeleteImportGraphDefOptions(
740 TF_ImportGraphDefOptions* opts);
741
742// Set the prefix to be prepended to the names of nodes in `graph_def` that will
743// be imported into `graph`. `prefix` is copied and has no lifetime
744// requirements.
745TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsSetPrefix(
746 TF_ImportGraphDefOptions* opts, const char* prefix);
747
748// Set the execution device for nodes in `graph_def`.
749// Only applies to nodes where a device was not already explicitly specified.
750// `device` is copied and has no lifetime requirements.
751TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsSetDefaultDevice(
752 TF_ImportGraphDefOptions* opts, const char* device);
753
754// Set whether to uniquify imported operation names. If true, imported operation
755// names will be modified if their name already exists in the graph. If false,
756// conflicting names will be treated as an error. Note that this option has no
757// effect if a prefix is set, since the prefix will guarantee all names are
758// unique. Defaults to false.
759TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsSetUniquifyNames(
760 TF_ImportGraphDefOptions* opts, unsigned char uniquify_names);
761
762// If true, the specified prefix will be modified if it already exists as an
763// operation name or prefix in the graph. If false, a conflicting prefix will be
764// treated as an error. This option has no effect if no prefix is specified.
765TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsSetUniquifyPrefix(
766 TF_ImportGraphDefOptions* opts, unsigned char uniquify_prefix);
767
768// Set any imported nodes with input `src_name:src_index` to have that input
769// replaced with `dst`. `src_name` refers to a node in the graph to be imported,
770// `dst` references a node already existing in the graph being imported into.
771// `src_name` is copied and has no lifetime requirements.
772TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsAddInputMapping(
773 TF_ImportGraphDefOptions* opts, const char* src_name, int src_index,
774 TF_Output dst);
775
776// Set any imported nodes with control input `src_name` to have that input
777// replaced with `dst`. `src_name` refers to a node in the graph to be imported,
778// `dst` references an operation already existing in the graph being imported
779// into. `src_name` is copied and has no lifetime requirements.
780TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsRemapControlDependency(
781 TF_ImportGraphDefOptions* opts, const char* src_name, TF_Operation* dst);
782
783// Cause the imported graph to have a control dependency on `oper`. `oper`
784// should exist in the graph being imported into.
785TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsAddControlDependency(
786 TF_ImportGraphDefOptions* opts, TF_Operation* oper);
787
788// Add an output in `graph_def` to be returned via the `return_outputs` output
789// parameter of TF_GraphImportGraphDef(). If the output is remapped via an input
790// mapping, the corresponding existing tensor in `graph` will be returned.
791// `oper_name` is copied and has no lifetime requirements.
792TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsAddReturnOutput(
793 TF_ImportGraphDefOptions* opts, const char* oper_name, int index);
794
795// Returns the number of return outputs added via
796// TF_ImportGraphDefOptionsAddReturnOutput().
797TF_CAPI_EXPORT extern int TF_ImportGraphDefOptionsNumReturnOutputs(
798 const TF_ImportGraphDefOptions* opts);
799
800// Add an operation in `graph_def` to be returned via the `return_opers` output
801// parameter of TF_GraphImportGraphDef(). `oper_name` is copied and has no
802// lifetime requirements.
803TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsAddReturnOperation(
804 TF_ImportGraphDefOptions* opts, const char* oper_name);
805
806// Returns the number of return operations added via
807// TF_ImportGraphDefOptionsAddReturnOperation().
808TF_CAPI_EXPORT extern int TF_ImportGraphDefOptionsNumReturnOperations(
809 const TF_ImportGraphDefOptions* opts);
810
811// TF_ImportGraphDefResults holds results that are generated by
812// TF_GraphImportGraphDefWithResults().
813typedef struct TF_ImportGraphDefResults TF_ImportGraphDefResults;
814
815// Fetches the return outputs requested via
816// TF_ImportGraphDefOptionsAddReturnOutput(). The number of fetched outputs is
817// returned in `num_outputs`. The array of return outputs is returned in
818// `outputs`. `*outputs` is owned by and has the lifetime of `results`.
819TF_CAPI_EXPORT extern void TF_ImportGraphDefResultsReturnOutputs(
820 TF_ImportGraphDefResults* results, int* num_outputs, TF_Output** outputs);
821
822// Fetches the return operations requested via
823// TF_ImportGraphDefOptionsAddReturnOperation(). The number of fetched
824// operations is returned in `num_opers`. The array of return operations is
825// returned in `opers`. `*opers` is owned by and has the lifetime of `results`.
826TF_CAPI_EXPORT extern void TF_ImportGraphDefResultsReturnOperations(
827 TF_ImportGraphDefResults* results, int* num_opers, TF_Operation*** opers);
828
829// Fetches any input mappings requested via
830// TF_ImportGraphDefOptionsAddInputMapping() that didn't appear in the GraphDef
831// and weren't used as input to any node in the imported graph def. The number
832// of fetched mappings is returned in `num_missing_unused_input_mappings`. The
833// array of each mapping's source node name is returned in `src_names`, and the
834// array of each mapping's source index is returned in `src_indexes`.
835//
836// `*src_names`, `*src_indexes`, and the memory backing each string in
837// `src_names` are owned by and have the lifetime of `results`.
838TF_CAPI_EXPORT extern void TF_ImportGraphDefResultsMissingUnusedInputMappings(
839 TF_ImportGraphDefResults* results, int* num_missing_unused_input_mappings,
840 const char*** src_names, int** src_indexes);
841
842// Deletes a results object returned by TF_GraphImportGraphDefWithResults().
843TF_CAPI_EXPORT extern void TF_DeleteImportGraphDefResults(
844 TF_ImportGraphDefResults* results);
845
846// Import the graph serialized in `graph_def` into `graph`. Returns nullptr and
847// a bad status on error. Otherwise, returns a populated
848// TF_ImportGraphDefResults instance. The returned instance must be deleted via
849// TF_DeleteImportGraphDefResults().
850TF_CAPI_EXPORT extern TF_ImportGraphDefResults*
851TF_GraphImportGraphDefWithResults(TF_Graph* graph, const TF_Buffer* graph_def,
852 const TF_ImportGraphDefOptions* options,
853 TF_Status* status);
854
855// Import the graph serialized in `graph_def` into `graph`.
856// Convenience function for when only return outputs are needed.
857//
858// `num_return_outputs` must be the number of return outputs added (i.e. the
859// result of TF_ImportGraphDefOptionsNumReturnOutputs()). If
860// `num_return_outputs` is non-zero, `return_outputs` must be of length
861// `num_return_outputs`. Otherwise it can be null.
862TF_CAPI_EXPORT extern void TF_GraphImportGraphDefWithReturnOutputs(
863 TF_Graph* graph, const TF_Buffer* graph_def,
864 const TF_ImportGraphDefOptions* options, TF_Output* return_outputs,
865 int num_return_outputs, TF_Status* status);
866
867// Import the graph serialized in `graph_def` into `graph`.
868// Convenience function for when no results are needed.
869TF_CAPI_EXPORT extern void TF_GraphImportGraphDef(
870 TF_Graph* graph, const TF_Buffer* graph_def,
871 const TF_ImportGraphDefOptions* options, TF_Status* status);
872
873// Adds a copy of function `func` and optionally its gradient function `grad`
874// to `g`. Once `func`/`grad` is added to `g`, it can be called by creating
875// an operation using the function's name.
876// Any changes to `func`/`grad` (including deleting it) done after this method
877// returns, won't affect the copy of `func`/`grad` in `g`.
878// If `func` or `grad` are already in `g`, TF_GraphCopyFunction has no
879// effect on them, but can establish the function->gradient relationship
880// between them if `func` does not already have a gradient. If `func` already
881// has a gradient different from `grad`, an error is returned.
882//
883// `func` must not be null.
884// If `grad` is null and `func` is not in `g`, `func` is added without a
885// gradient.
886// If `grad` is null and `func` is in `g`, TF_GraphCopyFunction is a noop.
887// `grad` must have appropriate signature as described in the doc of
888// GradientDef in tensorflow/core/framework/function.proto.
889//
890// If successful, status is set to OK and `func` and `grad` are added to `g`.
891// Otherwise, status is set to the encountered error and `g` is unmodified.
892TF_CAPI_EXPORT extern void TF_GraphCopyFunction(TF_Graph* g,
893 const TF_Function* func,
894 const TF_Function* grad,
895 TF_Status* status);
896
897// Returns the number of TF_Functions registered in `g`.
898TF_CAPI_EXPORT extern int TF_GraphNumFunctions(TF_Graph* g);
899
900// Fills in `funcs` with the TF_Function* registered in `g`.
901// `funcs` must point to an array of TF_Function* of length at least
902// `max_func`. In usual usage, max_func should be set to the result of
903// TF_GraphNumFunctions(g). In this case, all the functions registered in
904// `g` will be returned. Else, an unspecified subset.
905//
906// If successful, returns the number of TF_Function* successfully set in
907// `funcs` and sets status to OK. The caller takes ownership of
908// all the returned TF_Functions. They must be deleted with TF_DeleteFunction.
909// On error, returns 0, sets status to the encountered error, and the contents
910// of funcs will be undefined.
911TF_CAPI_EXPORT extern int TF_GraphGetFunctions(TF_Graph* g, TF_Function** funcs,
912 int max_func, TF_Status* status);
913
914// Note: The following function may fail on very large protos in the future.
915
916TF_CAPI_EXPORT extern void TF_OperationToNodeDef(TF_Operation* oper,
917 TF_Buffer* output_node_def,
918 TF_Status* status);
919
920typedef struct TF_WhileParams {
921 // The number of inputs to the while loop, i.e. the number of loop variables.
922 // This is the size of cond_inputs, body_inputs, and body_outputs.
923 const int ninputs;
924
925 // The while condition graph. The inputs are the current values of the loop
926 // variables. The output should be a scalar boolean.
927 TF_Graph* const cond_graph;
928 const TF_Output* const cond_inputs;
929 TF_Output cond_output;
930
931 // The loop body graph. The inputs are the current values of the loop
932 // variables. The outputs are the updated values of the loop variables.
933 TF_Graph* const body_graph;
934 const TF_Output* const body_inputs;
935 TF_Output* const body_outputs;
936
937 // Unique null-terminated name for this while loop. This is used as a prefix
938 // for created operations.
939 const char* name;
940} TF_WhileParams;
941
942// Creates a TF_WhileParams for creating a while loop in `g`. `inputs` are
943// outputs that already exist in `g` used as initial values for the loop
944// variables.
945//
946// The returned TF_WhileParams will have all fields initialized except
947// `cond_output`, `body_outputs`, and `name`. The `body_outputs` buffer will be
948// allocated to size `ninputs`. The caller should build `cond_graph` and
949// `body_graph` starting from the inputs, and store the final outputs in
950// `cond_output` and `body_outputs`.
951//
952// If `status` is OK, the caller must call either TF_FinishWhile or
953// TF_AbortWhile on the returned TF_WhileParams. If `status` isn't OK, the
954// returned TF_WhileParams is not valid, and the caller should not call
955// TF_FinishWhile() or TF_AbortWhile().
956//
957// Missing functionality (TODO):
958// - Gradients
959// - Reference-type inputs
960// - Directly referencing external tensors from the cond/body graphs (this is
961// possible in the Python API)
962TF_CAPI_EXPORT extern TF_WhileParams TF_NewWhile(TF_Graph* g, TF_Output* inputs,
963 int ninputs,
964 TF_Status* status);
965
966// Builds the while loop specified by `params` and returns the output tensors of
967// the while loop in `outputs`. `outputs` should be allocated to size
968// `params.ninputs`.
969//
970// `params` is no longer valid once this returns.
971//
972// Either this or TF_AbortWhile() must be called after a successful
973// TF_NewWhile() call.
974TF_CAPI_EXPORT extern void TF_FinishWhile(const TF_WhileParams* params,
975 TF_Status* status,
976 TF_Output* outputs);
977
978// Frees `params`s resources without building a while loop. `params` is no
979// longer valid after this returns. Either this or TF_FinishWhile() must be
980// called after a successful TF_NewWhile() call.
981TF_CAPI_EXPORT extern void TF_AbortWhile(const TF_WhileParams* params);
982
983// Adds operations to compute the partial derivatives of sum of `y`s w.r.t `x`s,
984// i.e., d(y_1 + y_2 + ...)/dx_1, d(y_1 + y_2 + ...)/dx_2...
985//
986// `dx` are used as initial gradients (which represent the symbolic partial
987// derivatives of some loss function `L` w.r.t. `y`).
988// `dx` must be nullptr or have size `ny`.
989// If `dx` is nullptr, the implementation will use dx of `OnesLike` for all
990// shapes in `y`.
991// The partial derivatives are returned in `dy`. `dy` should be allocated to
992// size `nx`.
993//
994// Gradient nodes are automatically named under the "gradients/" prefix. To
995// guarantee name uniqueness, subsequent calls to the same graph will
996// append an incremental tag to the prefix: "gradients_1/", "gradients_2/", ...
997// See TF_AddGradientsWithPrefix, which provides a means to specify a custom
998// name prefix for operations added to a graph to compute the gradients.
999//
1000// WARNING: This function does not yet support all the gradients that python
1001// supports. See
1002// https://www.tensorflow.org/code/tensorflow/cc/gradients/README.md
1003// for instructions on how to add C++ more gradients.
1004TF_CAPI_EXPORT void TF_AddGradients(TF_Graph* g, TF_Output* y, int ny,
1005 TF_Output* x, int nx, TF_Output* dx,
1006 TF_Status* status, TF_Output* dy);
1007
1008// Adds operations to compute the partial derivatives of sum of `y`s w.r.t `x`s,
1009// i.e., d(y_1 + y_2 + ...)/dx_1, d(y_1 + y_2 + ...)/dx_2...
1010// This is a variant of TF_AddGradients that allows to caller to pass a custom
1011// name prefix to the operations added to a graph to compute the gradients.
1012//
1013// `dx` are used as initial gradients (which represent the symbolic partial
1014// derivatives of some loss function `L` w.r.t. `y`).
1015// `dx` must be nullptr or have size `ny`.
1016// If `dx` is nullptr, the implementation will use dx of `OnesLike` for all
1017// shapes in `y`.
1018// The partial derivatives are returned in `dy`. `dy` should be allocated to
1019// size `nx`.
1020// `prefix` names the scope into which all gradients operations are being added.
1021// `prefix` must be unique within the provided graph otherwise this operation
1022// will fail. If `prefix` is nullptr, the default prefixing behaviour takes
1023// place, see TF_AddGradients for more details.
1024//
1025// WARNING: This function does not yet support all the gradients that python
1026// supports. See
1027// https://www.tensorflow.org/code/tensorflow/cc/gradients/README.md
1028// for instructions on how to add C++ more gradients.
1029TF_CAPI_EXPORT void TF_AddGradientsWithPrefix(TF_Graph* g, const char* prefix,
1030 TF_Output* y, int ny,
1031 TF_Output* x, int nx,
1032 TF_Output* dx, TF_Status* status,
1033 TF_Output* dy);
1034
1035// Create a TF_Function from a TF_Graph
1036//
1037// Params:
1038// fn_body - the graph whose operations (or subset of whose operations) will be
1039// converted to TF_Function.
1040// fn_name - the name of the new TF_Function. Should match the operation
1041// name (OpDef.name) regexp [A-Z][A-Za-z0-9_.\\-/]*.
1042// If `append_hash_to_fn_name` is false, `fn_name` must be distinct
1043// from other function and operation names (at least those
1044// registered in graphs where this function will be used).
1045// append_hash_to_fn_name - Must be 0 or 1. If set to 1, the actual name
1046// of the function will be `fn_name` appended with
1047// '_<hash_of_this_function's_definition>'.
1048// If set to 0, the function's name will be `fn_name`.
1049// num_opers - `num_opers` contains the number of elements in the `opers` array
1050// or a special value of -1 meaning that no array is given.
1051// The distinction between an empty array of operations and no
1052// array of operations is necessary to distinguish the case of
1053// creating a function with no body (e.g. identity or permutation)
1054// and the case of creating a function whose body contains all
1055// the nodes in the graph (except for the automatic skipping, see
1056// below).
1057// opers - Array of operations to become the body of the function or null.
1058// - If no array is given (`num_opers` = -1), all the
1059// operations in `fn_body` will become part of the function
1060// except operations referenced in `inputs`. These operations
1061// must have a single output (these operations are typically
1062// placeholders created for the sole purpose of representing
1063// an input. We can relax this constraint if there are
1064// compelling use cases).
1065// - If an array is given (`num_opers` >= 0), all operations
1066// in it will become part of the function. In particular, no
1067// automatic skipping of dummy input operations is performed.
1068// ninputs - number of elements in `inputs` array
1069// inputs - array of TF_Outputs that specify the inputs to the function.
1070// If `ninputs` is zero (the function takes no inputs), `inputs`
1071// can be null. The names used for function inputs are normalized
1072// names of the operations (usually placeholders) pointed to by
1073// `inputs`. These operation names should start with a letter.
1074// Normalization will convert all letters to lowercase and
1075// non-alphanumeric characters to '_' to make resulting names match
1076// the "[a-z][a-z0-9_]*" pattern for operation argument names.
1077// `inputs` cannot contain the same tensor twice.
1078// noutputs - number of elements in `outputs` array
1079// outputs - array of TF_Outputs that specify the outputs of the function.
1080// If `noutputs` is zero (the function returns no outputs), `outputs`
1081// can be null. `outputs` can contain the same tensor more than once.
1082// output_names - The names of the function's outputs. `output_names` array
1083// must either have the same length as `outputs`
1084// (i.e. `noutputs`) or be null. In the former case,
1085// the names should match the regular expression for ArgDef
1086// names - "[a-z][a-z0-9_]*". In the latter case,
1087// names for outputs will be generated automatically.
1088// opts - various options for the function, e.g. XLA's inlining control.
1089// description - optional human-readable description of this function.
1090// status - Set to OK on success and an appropriate error on failure.
1091//
1092// Note that when the same TF_Output is listed as both an input and an output,
1093// the corresponding function's output will equal to this input,
1094// instead of the original node's output.
1095//
1096// Callers must also satisfy the following constraints:
1097// - `inputs` cannot refer to TF_Outputs within a control flow context. For
1098// example, one cannot use the output of "switch" node as input.
1099// - `inputs` and `outputs` cannot have reference types. Reference types are
1100// not exposed through C API and are being replaced with Resources. We support
1101// reference types inside function's body to support legacy code. Do not
1102// use them in new code.
1103// - Every node in the function's body must have all of its inputs (including
1104// control inputs). In other words, for every node in the body, each input
1105// must be either listed in `inputs` or must come from another node in
1106// the body. In particular, it is an error to have a control edge going from
1107// a node outside of the body into a node in the body. This applies to control
1108// edges going from nodes referenced in `inputs` to nodes in the body when
1109// the former nodes are not in the body (automatically skipped or not
1110// included in explicitly specified body).
1111//
1112// Returns:
1113// On success, a newly created TF_Function instance. It must be deleted by
1114// calling TF_DeleteFunction.
1115//
1116// On failure, null.
1117TF_CAPI_EXPORT extern TF_Function* TF_GraphToFunction(
1118 const TF_Graph* fn_body, const char* fn_name,
1119 unsigned char append_hash_to_fn_name, int num_opers,
1120 const TF_Operation* const* opers, int ninputs, const TF_Output* inputs,
1121 int noutputs, const TF_Output* outputs, const char* const* output_names,
1122 const TF_FunctionOptions* opts, const char* description, TF_Status* status);
1123
1124// Similar to TF_GraphToFunction but allows specifying control outputs of the
1125// function.
1126//
1127// The arguments of TF_GraphToFunction have the same meaning, but the new
1128// arguments are as follows:
1129//
1130// ncontrol_outputs: Number of control outputs of the function.
1131// control_outputs: vector of TF_Operation objects to be marked as control
1132// outputs of the function. Operations marked as control outputs are
1133// guaranteed to execute.
1134// control_output_names: Optional. If not nullptr, vector of strings, one
1135// per control output, with their names to be added to the function's
1136// OpDef.
1137TF_CAPI_EXPORT extern TF_Function* TF_GraphToFunctionWithControlOutputs(
1138 const TF_Graph* fn_body, const char* fn_name,
1139 unsigned char append_hash_to_fn_name, int num_opers,
1140 const TF_Operation* const* opers, int ninputs, const TF_Output* inputs,
1141 int noutputs, const TF_Output* outputs, const char* const* output_names,
1142 int ncontrol_outputs, const TF_Operation* const* control_outputs,
1143 const char* const* control_output_names, const TF_FunctionOptions* opts,
1144 const char* description, TF_Status* status);
1145
1146// Returns the name of the graph function.
1147// The return value points to memory that is only usable until the next
1148// mutation to *func.
1149TF_CAPI_EXPORT extern const char* TF_FunctionName(TF_Function* func);
1150
1151// Write out a serialized representation of `func` (as a FunctionDef protocol
1152// message) to `output_func_def` (allocated by TF_NewBuffer()).
1153// `output_func_def`'s underlying buffer will be freed when TF_DeleteBuffer()
1154// is called.
1155//
1156// May fail on very large graphs in the future.
1157TF_CAPI_EXPORT extern void TF_FunctionToFunctionDef(TF_Function* func,
1158 TF_Buffer* output_func_def,
1159 TF_Status* status);
1160
1161// Construct and return the function whose FunctionDef representation is
1162// serialized in `proto`. `proto_len` must equal the number of bytes
1163// pointed to by `proto`.
1164// Returns:
1165// On success, a newly created TF_Function instance. It must be deleted by
1166// calling TF_DeleteFunction.
1167//
1168// On failure, null.
1169TF_CAPI_EXPORT extern TF_Function* TF_FunctionImportFunctionDef(
1170 const void* proto, size_t proto_len, TF_Status* status);
1171
1172// Sets function attribute named `attr_name` to value stored in `proto`.
1173// If this attribute is already set to another value, it is overridden.
1174// `proto` should point to a sequence of bytes of length `proto_len`
1175// representing a binary serialization of an AttrValue protocol
1176// buffer.
1177TF_CAPI_EXPORT extern void TF_FunctionSetAttrValueProto(TF_Function* func,
1178 const char* attr_name,
1179 const void* proto,
1180 size_t proto_len,
1181 TF_Status* status);
1182
1183// Sets `output_attr_value` to the binary-serialized AttrValue proto
1184// representation of the value of the `attr_name` attr of `func`.
1185// If `attr_name` attribute is not present, status is set to an error.
1186TF_CAPI_EXPORT extern void TF_FunctionGetAttrValueProto(
1187 TF_Function* func, const char* attr_name, TF_Buffer* output_attr_value,
1188 TF_Status* status);
1189
1190// Frees the memory used by the `func` struct.
1191// TF_DeleteFunction is a noop if `func` is null.
1192// Deleting a function does not remove it from any graphs it was copied to.
1193TF_CAPI_EXPORT extern void TF_DeleteFunction(TF_Function* func);
1194
1195// Attempts to evaluate `output`. This will only be possible if `output` doesn't
1196// depend on any graph inputs (this function is safe to call if this isn't the
1197// case though).
1198//
1199// If the evaluation is successful, this function returns true and `output`s
1200// value is returned in `result`. Otherwise returns false. An error status is
1201// returned if something is wrong with the graph or input. Note that this may
1202// return false even if no error status is set.
1203TF_CAPI_EXPORT extern unsigned char TF_TryEvaluateConstant(TF_Graph* graph,
1204 TF_Output output,
1205 TF_Tensor** result,
1206 TF_Status* status);
1207
1208// TODO(josh11b): Register OpDef, available to all operations added
1209// to this graph.
1210
1211// --------------------------------------------------------------------------
1212// API for driving Graph execution.
1213
1214typedef struct TF_Session TF_Session;
1215
1216// Return a new execution session with the associated graph, or NULL on
1217// error. Does not take ownership of any input parameters.
1218//
1219// *`graph` must be a valid graph (not deleted or nullptr). `graph` will be
1220// kept alive for the lifetime of the returned TF_Session. New nodes can still
1221// be added to `graph` after this call.
1222TF_CAPI_EXPORT extern TF_Session* TF_NewSession(TF_Graph* graph,
1223 const TF_SessionOptions* opts,
1224 TF_Status* status);
1225
1226// This function creates a new TF_Session (which is created on success) using
1227// `session_options`, and then initializes state (restoring tensors and other
1228// assets) using `run_options`.
1229//
1230// Any NULL and non-NULL value combinations for (`run_options, `meta_graph_def`)
1231// are valid.
1232//
1233// - `export_dir` must be set to the path of the exported SavedModel.
1234// - `tags` must include the set of tags used to identify one MetaGraphDef in
1235// the SavedModel.
1236// - `graph` must be a graph newly allocated with TF_NewGraph().
1237//
1238// If successful, populates `graph` with the contents of the Graph and
1239// `meta_graph_def` with the MetaGraphDef of the loaded model.
1240TF_CAPI_EXPORT extern TF_Session* TF_LoadSessionFromSavedModel(
1241 const TF_SessionOptions* session_options, const TF_Buffer* run_options,
1242 const char* export_dir, const char* const* tags, int tags_len,
1243 TF_Graph* graph, TF_Buffer* meta_graph_def, TF_Status* status);
1244
1245// Close a session.
1246//
1247// Contacts any other processes associated with the session, if applicable.
1248// May not be called after TF_DeleteSession().
1249TF_CAPI_EXPORT extern void TF_CloseSession(TF_Session*, TF_Status* status);
1250
1251// Destroy a session object.
1252//
1253// Even if error information is recorded in *status, this call discards all
1254// local resources associated with the session. The session may not be used
1255// during or after this call (and the session drops its reference to the
1256// corresponding graph).
1257TF_CAPI_EXPORT extern void TF_DeleteSession(TF_Session*, TF_Status* status);
1258
1259// Run the graph associated with the session starting with the supplied inputs
1260// (inputs[0,ninputs-1] with corresponding values in input_values[0,ninputs-1]).
1261//
1262// Any NULL and non-NULL value combinations for (`run_options`,
1263// `run_metadata`) are valid.
1264//
1265// - `run_options` may be NULL, in which case it will be ignored; or
1266// non-NULL, in which case it must point to a `TF_Buffer` containing the
1267// serialized representation of a `RunOptions` protocol buffer.
1268// - `run_metadata` may be NULL, in which case it will be ignored; or
1269// non-NULL, in which case it must point to an empty, freshly allocated
1270// `TF_Buffer` that may be updated to contain the serialized representation
1271// of a `RunMetadata` protocol buffer.
1272//
1273// The caller retains ownership of `input_values` (which can be deleted using
1274// TF_DeleteTensor). The caller also retains ownership of `run_options` and/or
1275// `run_metadata` (when not NULL) and should manually call TF_DeleteBuffer on
1276// them.
1277//
1278// On success, the tensors corresponding to outputs[0,noutputs-1] are placed in
1279// output_values[]. Ownership of the elements of output_values[] is transferred
1280// to the caller, which must eventually call TF_DeleteTensor on them.
1281//
1282// On failure, output_values[] contains NULLs.
1283TF_CAPI_EXPORT extern void TF_SessionRun(
1284 TF_Session* session,
1285 // RunOptions
1286 const TF_Buffer* run_options,
1287 // Input tensors
1288 const TF_Output* inputs, TF_Tensor* const* input_values, int ninputs,
1289 // Output tensors
1290 const TF_Output* outputs, TF_Tensor** output_values, int noutputs,
1291 // Target operations
1292 const TF_Operation* const* target_opers, int ntargets,
1293 // RunMetadata
1294 TF_Buffer* run_metadata,
1295 // Output status
1296 TF_Status*);
1297
1298// Set up the graph with the intended feeds (inputs) and fetches (outputs) for a
1299// sequence of partial run calls.
1300//
1301// On success, returns a handle that is used for subsequent PRun calls. The
1302// handle should be deleted with TF_DeletePRunHandle when it is no longer
1303// needed.
1304//
1305// On failure, out_status contains a tensorflow::Status with an error
1306// message. *handle is set to nullptr.
1307TF_CAPI_EXPORT extern void TF_SessionPRunSetup(
1308 TF_Session*,
1309 // Input names
1310 const TF_Output* inputs, int ninputs,
1311 // Output names
1312 const TF_Output* outputs, int noutputs,
1313 // Target operations
1314 const TF_Operation* const* target_opers, int ntargets,
1315 // Output handle
1316 const char** handle,
1317 // Output status
1318 TF_Status*);
1319
1320// Continue to run the graph with additional feeds and fetches. The
1321// execution state is uniquely identified by the handle.
1322TF_CAPI_EXPORT extern void TF_SessionPRun(
1323 TF_Session*, const char* handle,
1324 // Input tensors
1325 const TF_Output* inputs, TF_Tensor* const* input_values, int ninputs,
1326 // Output tensors
1327 const TF_Output* outputs, TF_Tensor** output_values, int noutputs,
1328 // Target operations
1329 const TF_Operation* const* target_opers, int ntargets,
1330 // Output status
1331 TF_Status*);
1332
1333// Deletes a handle allocated by TF_SessionPRunSetup.
1334// Once called, no more calls to TF_SessionPRun should be made.
1335TF_CAPI_EXPORT extern void TF_DeletePRunHandle(const char* handle);
1336
1337// --------------------------------------------------------------------------
1338// The deprecated session API. Please switch to the above instead of
1339// TF_ExtendGraph(). This deprecated API can be removed at any time without
1340// notice.
1341
1342typedef struct TF_DeprecatedSession TF_DeprecatedSession;
1343
1344TF_CAPI_EXPORT extern TF_DeprecatedSession* TF_NewDeprecatedSession(
1345 const TF_SessionOptions*, TF_Status* status);
1346TF_CAPI_EXPORT extern void TF_CloseDeprecatedSession(TF_DeprecatedSession*,
1347 TF_Status* status);
1348TF_CAPI_EXPORT extern void TF_DeleteDeprecatedSession(TF_DeprecatedSession*,
1349 TF_Status* status);
1350TF_CAPI_EXPORT extern void TF_Reset(const TF_SessionOptions* opt,
1351 const char** containers, int ncontainers,
1352 TF_Status* status);
1353// Treat the bytes proto[0,proto_len-1] as a serialized GraphDef and
1354// add the nodes in that GraphDef to the graph for the session.
1355//
1356// Prefer use of TF_Session and TF_GraphImportGraphDef over this.
1357TF_CAPI_EXPORT extern void TF_ExtendGraph(TF_DeprecatedSession*,
1358 const void* proto, size_t proto_len,
1359 TF_Status*);
1360
1361// See TF_SessionRun() above.
1362TF_CAPI_EXPORT extern void TF_Run(TF_DeprecatedSession*,
1363 const TF_Buffer* run_options,
1364 const char** input_names, TF_Tensor** inputs,
1365 int ninputs, const char** output_names,
1366 TF_Tensor** outputs, int noutputs,
1367 const char** target_oper_names, int ntargets,
1368 TF_Buffer* run_metadata, TF_Status*);
1369
1370// See TF_SessionPRunSetup() above.
1371TF_CAPI_EXPORT extern void TF_PRunSetup(TF_DeprecatedSession*,
1372 const char** input_names, int ninputs,
1373 const char** output_names, int noutputs,
1374 const char** target_oper_names,
1375 int ntargets, const char** handle,
1376 TF_Status*);
1377
1378// See TF_SessionPRun above.
1379TF_CAPI_EXPORT extern void TF_PRun(TF_DeprecatedSession*, const char* handle,
1380 const char** input_names, TF_Tensor** inputs,
1381 int ninputs, const char** output_names,
1382 TF_Tensor** outputs, int noutputs,
1383 const char** target_oper_names, int ntargets,
1384 TF_Status*);
1385
1386typedef struct TF_DeviceList TF_DeviceList;
1387
1388// Lists all devices in a TF_Session.
1389//
1390// Caller takes ownership of the returned TF_DeviceList* which must eventually
1391// be freed with a call to TF_DeleteDeviceList.
1392TF_CAPI_EXPORT extern TF_DeviceList* TF_SessionListDevices(TF_Session* session,
1393 TF_Status* status);
1394
1395// Lists all devices in a TF_Session.
1396//
1397// Caller takes ownership of the returned TF_DeviceList* which must eventually
1398// be freed with a call to TF_DeleteDeviceList.
1399TF_CAPI_EXPORT extern TF_DeviceList* TF_DeprecatedSessionListDevices(
1400 TF_DeprecatedSession* session, TF_Status* status);
1401
1402// Deallocates the device list.
1403TF_CAPI_EXPORT extern void TF_DeleteDeviceList(TF_DeviceList* list);
1404
1405// Counts the number of elements in the device list.
1406TF_CAPI_EXPORT extern int TF_DeviceListCount(const TF_DeviceList* list);
1407
1408// Retrieves the full name of the device (e.g. /job:worker/replica:0/...)
1409// The return value will be a pointer to a null terminated string. The caller
1410// must not modify or delete the string. It will be deallocated upon a call to
1411// TF_DeleteDeviceList.
1412//
1413// If index is out of bounds, an error code will be set in the status object,
1414// and a null pointer will be returned.
1415TF_CAPI_EXPORT extern const char* TF_DeviceListName(const TF_DeviceList* list,
1416 int index,
1417 TF_Status* status);
1418
1419// Retrieves the type of the device at the given index.
1420//
1421// The caller must not modify or delete the string. It will be deallocated upon
1422// a call to TF_DeleteDeviceList.
1423//
1424// If index is out of bounds, an error code will be set in the status object,
1425// and a null pointer will be returned.
1426TF_CAPI_EXPORT extern const char* TF_DeviceListType(const TF_DeviceList* list,
1427 int index,
1428 TF_Status* status);
1429
1430// Retrieve the amount of memory associated with a given device.
1431//
1432// If index is out of bounds, an error code will be set in the status object,
1433// and -1 will be returned.
1434TF_CAPI_EXPORT extern int64_t TF_DeviceListMemoryBytes(
1435 const TF_DeviceList* list, int index, TF_Status* status);
1436
1437// Retrieve the incarnation number of a given device.
1438//
1439// If index is out of bounds, an error code will be set in the status object,
1440// and 0 will be returned.
1441TF_CAPI_EXPORT extern uint64_t TF_DeviceListIncarnation(
1442 const TF_DeviceList* list, int index, TF_Status* status);
1443
1444// --------------------------------------------------------------------------
1445// Load plugins containing custom ops and kernels
1446
1447// TF_Library holds information about dynamically loaded TensorFlow plugins.
1448typedef struct TF_Library TF_Library;
1449
1450// Load the library specified by library_filename and register the ops and
1451// kernels present in that library.
1452//
1453// Pass "library_filename" to a platform-specific mechanism for dynamically
1454// loading a library. The rules for determining the exact location of the
1455// library are platform-specific and are not documented here.
1456//
1457// On success, place OK in status and return the newly created library handle.
1458// The caller owns the library handle.
1459//
1460// On failure, place an error status in status and return NULL.
1461TF_CAPI_EXPORT extern TF_Library* TF_LoadLibrary(const char* library_filename,
1462 TF_Status* status);
1463
1464// Get the OpList of OpDefs defined in the library pointed by lib_handle.
1465//
1466// Returns a TF_Buffer. The memory pointed to by the result is owned by
1467// lib_handle. The data in the buffer will be the serialized OpList proto for
1468// ops defined in the library.
1469TF_CAPI_EXPORT extern TF_Buffer TF_GetOpList(TF_Library* lib_handle);
1470
1471// Frees the memory associated with the library handle.
1472// Does NOT unload the library.
1473TF_CAPI_EXPORT extern void TF_DeleteLibraryHandle(TF_Library* lib_handle);
1474
1475// Get the OpList of all OpDefs defined in this address space.
1476// Returns a TF_Buffer, ownership of which is transferred to the caller
1477// (and can be freed using TF_DeleteBuffer).
1478//
1479// The data in the buffer will be the serialized OpList proto for ops registered
1480// in this address space.
1481TF_CAPI_EXPORT extern TF_Buffer* TF_GetAllOpList(void);
1482
1483// TF_ApiDefMap encapsulates a collection of API definitions for an operation.
1484//
1485// This object maps the name of a TensorFlow operation to a description of the
1486// API to generate for it, as defined by the ApiDef protocol buffer (
1487// https://www.tensorflow.org/code/tensorflow/core/framework/api_def.proto)
1488//
1489// The ApiDef messages are typically used to generate convenience wrapper
1490// functions for TensorFlow operations in various language bindings.
1491typedef struct TF_ApiDefMap TF_ApiDefMap;
1492
1493// Creates a new TF_ApiDefMap instance.
1494//
1495// Params:
1496// op_list_buffer - TF_Buffer instance containing serialized OpList
1497// protocol buffer. (See
1498// https://www.tensorflow.org/code/tensorflow/core/framework/op_def.proto
1499// for the OpList proto definition).
1500// status - Set to OK on success and an appropriate error on failure.
1501TF_CAPI_EXPORT extern TF_ApiDefMap* TF_NewApiDefMap(TF_Buffer* op_list_buffer,
1502 TF_Status* status);
1503
1504// Deallocates a TF_ApiDefMap.
1505TF_CAPI_EXPORT extern void TF_DeleteApiDefMap(TF_ApiDefMap* apimap);
1506
1507// Add ApiDefs to the map.
1508//
1509// `text` corresponds to a text representation of an ApiDefs protocol message.
1510// (https://www.tensorflow.org/code/tensorflow/core/framework/api_def.proto).
1511//
1512// The provided ApiDefs will be merged with existing ones in the map, with
1513// precedence given to the newly added version in case of conflicts with
1514// previous calls to TF_ApiDefMapPut.
1515TF_CAPI_EXPORT extern void TF_ApiDefMapPut(TF_ApiDefMap* api_def_map,
1516 const char* text, size_t text_len,
1517 TF_Status* status);
1518
1519// Returns a serialized ApiDef protocol buffer for the TensorFlow operation
1520// named `name`.
1521TF_CAPI_EXPORT extern TF_Buffer* TF_ApiDefMapGet(TF_ApiDefMap* api_def_map,
1522 const char* name,
1523 size_t name_len,
1524 TF_Status* status);
1525
1526// --------------------------------------------------------------------------
1527// Kernel definition information.
1528
1529// Returns a serialized KernelList protocol buffer containing KernelDefs for all
1530// registered kernels.
1531TF_CAPI_EXPORT extern TF_Buffer* TF_GetAllRegisteredKernels(TF_Status* status);
1532
1533// Returns a serialized KernelList protocol buffer containing KernelDefs for all
1534// kernels registered for the operation named `name`.
1535TF_CAPI_EXPORT extern TF_Buffer* TF_GetRegisteredKernelsForOp(
1536 const char* name, TF_Status* status);
1537
1538// Update edge, switch input/ output in a node
1539TF_CAPI_EXPORT extern void TF_UpdateEdge(TF_Graph* graph, TF_Output new_src,
1540 TF_Input dst, TF_Status* status);
1541
1542// --------------------------------------------------------------------------
1543// In-process TensorFlow server functionality, for use in distributed training.
1544// A Server instance encapsulates a set of devices and a Session target that
1545// can participate in distributed training. A server belongs to a cluster
1546// (specified by a ClusterSpec), and corresponds to a particular task in a
1547// named job. The server can communicate with any other server in the same
1548// cluster.
1549
1550// In-process TensorFlow server.
1551typedef struct TF_Server TF_Server;
1552
1553// Creates a new in-process TensorFlow server configured using a serialized
1554// ServerDef protocol buffer provided via `proto` and `proto_len`.
1555//
1556// The server will not serve any requests until TF_ServerStart is invoked.
1557// The server will stop serving requests once TF_ServerStop or
1558// TF_DeleteServer is invoked.
1559TF_CAPI_EXPORT extern TF_Server* TF_NewServer(const void* proto,
1560 size_t proto_len,
1561 TF_Status* status);
1562
1563// Starts an in-process TensorFlow server.
1564TF_CAPI_EXPORT extern void TF_ServerStart(TF_Server* server, TF_Status* status);
1565
1566// Stops an in-process TensorFlow server.
1567TF_CAPI_EXPORT extern void TF_ServerStop(TF_Server* server, TF_Status* status);
1568
1569// Blocks until the server has been successfully stopped (via TF_ServerStop or
1570// TF_ServerClose).
1571TF_CAPI_EXPORT extern void TF_ServerJoin(TF_Server* server, TF_Status* status);
1572
1573// Returns the target string that can be provided to TF_SetTarget() to connect
1574// a TF_Session to `server`.
1575//
1576// The returned string is valid only until TF_DeleteServer is invoked.
1577TF_CAPI_EXPORT extern const char* TF_ServerTarget(TF_Server* server);
1578
1579// Destroy an in-process TensorFlow server, frees memory. If server is running
1580// it will be stopped and joined.
1581TF_CAPI_EXPORT extern void TF_DeleteServer(TF_Server* server);
1582
1583// Register a listener method that processes printed messages.
1584//
1585// If any listeners are registered, the print operator will call all listeners
1586// with the printed messages and immediately return without writing to the
1587// logs.
1588TF_CAPI_EXPORT extern void TF_RegisterLogListener(
1589 void (*listener)(const char*));
1590
1591// Register a FileSystem plugin from filename `plugin_filename`.
1592//
1593// On success, place OK in status.
1594// On failure, place an error status in status.
1595TF_CAPI_EXPORT extern void TF_RegisterFilesystemPlugin(
1596 const char* plugin_filename, TF_Status* status);
1597
1598#ifdef __cplusplus
1599} /* end extern "C" */
1600#endif
1601
1602#endif // TENSORFLOW_C_C_API_H_
1603