"Hello TensorFlow!" using the C API

For learning purposes, how to code this Python example using the TensorFlow C API ?

import tensorflow as tf
hello = tf.constant("hello TensorFlow!")
sess=tf.Session()
print(sess.run(hello))

I have tried it this way:

#include <string.h>
#include <iostream.h>
#include "c_api.h"

int main( int argc, char ** argv ) 
{
  TF_Graph * graph = TF_NewGraph();
  TF_SessionOptions * options = TF_NewSessionOptions();
  TF_Status * status = TF_NewStatus();
  TF_Session * session = TF_NewSession( graph, options, status );
  char hello[] = "Hello TensorFlow!";
  TF_Tensor * tensor = TF_AllocateTensor( TF_STRING, 0, 0, 8 + TF_StringEncodedSize( strlen( hello ) ) );
  TF_OperationDescription * operationDescription = TF_NewOperation( graph, "Const", "hello" );
  TF_Operation * operation; 
  struct TF_Output * output;

  TF_StringEncode( hello, strlen( hello ), 8 + ( char * ) TF_TensorData( tensor ), TF_StringEncodedSize( strlen( hello ) ), status );
  TF_SetAttrTensor( operationDescription, "value", tensor, status );
  TF_SetAttrType( operationDescription, "dtype", TF_TensorType( tensor ) );
  operation = TF_FinishOperation( operationDescription, status );

  output->oper = operation;
  output->index = 0;

  TF_SessionRun( session, 0,
                 0, 0, 0,  // Inputs
                 output, &tensor, 1,  // Outputs
                 &operation, 1,  // Operations
                 0, status );

  printf( "%i", TF_GetCode( status ) );

  TF_CloseSession( session, status );
  TF_DeleteSession( session, status );
  TF_DeleteStatus( status );
  TF_DeleteSessionOptions( options );  

  return 0;
}

I am testing it on Windows using the TensorFlow.dll from: http://ci.tensorflow.org/view/Nightly/job/nightly-libtensorflow-windows/lastSuccessfulBuild/artifact/lib_package/libtensorflow-cpu-windows-x86_64.zip

The above code GPFs on the TF_SessionRun() call. Once we find a solution for that, how to retrieve the output ? Should a different tensor be used for the output ? The above code reuses it in both the output and the operation.

many thanks

Upvotes: 8

Views: 9490

Answers (3)

Ilya Evdokimov
Ilya Evdokimov

Reputation: 1

The example will work on Linux with TensorFlow installed as described here https://www.tensorflow.org/install/lang_c with changed include directives:

#include <stdio.h>
#include <string.h>
#include <tensorflow/c/c_api.h>

To build it is enough to execute

gcc hello_tf.c -ltensorflow -o hello_tf

as it was said in TensorFlow docs.

Upvotes: 0

There was a bug to solve beside the offset initialization. This version seems to work fine:

#include <iostream.h>
#include "c_api.h"

int main( int argc, char ** argv ) 
{
  TF_Graph * graph = TF_NewGraph();
  TF_SessionOptions * options = TF_NewSessionOptions();
  TF_Status * status = TF_NewStatus();
  TF_Session * session = TF_NewSession( graph, options, status );
  char hello[] = "Hello TensorFlow!";
  TF_Tensor * tensor = TF_AllocateTensor( TF_STRING, 0, 0, 8 + TF_StringEncodedSize( strlen( hello ) ) );
  TF_Tensor * tensorOutput;
  TF_OperationDescription * operationDescription = TF_NewOperation( graph, "Const", "hello" );
  TF_Operation * operation; 
  struct TF_Output output;

  TF_StringEncode( hello, strlen( hello ), 8 + ( char * ) TF_TensorData( tensor ), TF_StringEncodedSize( strlen( hello ) ), status );
  memset( TF_TensorData( tensor ), 0, 8 );
  TF_SetAttrTensor( operationDescription, "value", tensor, status );
  TF_SetAttrType( operationDescription, "dtype", TF_TensorType( tensor ) );
  operation = TF_FinishOperation( operationDescription, status );

  output.oper = operation;
  output.index = 0;

  TF_SessionRun( session, 0,
                 0, 0, 0,  // Inputs
                 &output, &tensorOutput, 1,  // Outputs
                 &operation, 1,  // Operations
                 0, status );

  printf( "status code: %i\n", TF_GetCode( status ) );
  printf( "%s\n", ( ( char * ) TF_TensorData( tensorOutput ) ) + 9 );

  TF_CloseSession( session, status );
  TF_DeleteSession( session, status );
  TF_DeleteStatus( status );
  TF_DeleteSessionOptions( options );  

  return 0;
}

Do we have to delete the tensorOutput ? Not sure why we have to add 9 (instead of 8) to get the beginning of the string.

Upvotes: 9

ash
ash

Reputation: 6751

TF_STRING tensors are encoded using the format described here. In your code, you accounted for space (8 bytes) to encode the one offset, but didn't actually initialize it. To do that, you'd want to add something like:

memset(TF_TensorData(tensor), 0, 8);

Before the call to TF_SetAttrTensor, as that will set the "offset" of the string element to 0 (which the where you're encoding the one string value).

To your second question: You aren't actually re-using the same tensor pointer. The comments for TF_SessionRun suggest that TF_SessionRun is allocating a new TF_Tensor object that the caller takes ownership of. So, in your code snippet, the tensor variable is being overwritten to point to a newly allocated tensor.

Hope that helps.

Upvotes: 1

Related Questions