Documentation

Create a C++ Client

This example shows how to write a MATLAB® Production Server™ client using the C client API. The client application calls the addmatrix function you compiled in Package Deployable Archives with Production Server Compiler App and deployed in Share a Deployable Archive on the Server Instance (MATLAB Production Server).

Create a C++ MATLAB Production Server client application:

  1. Create a file called addmatrix_client.cpp.

  2. Using a text editor, open addmatrix_client.cpp.

  3. Add the following include statements to the file:

    #include <iostream>
    #include <mps/client.h>

    Note

    The header files for the MATLAB Production Server C client API are located in the matlabroot/toolbox/compiler_sdk/mps_client/c/include/mps folder. folder.

  4. Add the main() method to the application.

    int main ( void )
    {
    } 
  5. Initialize the client runtime.

    mpsClientRuntime* mpsruntime = mpsInitializeEx(MPS_CLIENT_1_1);
  6. Create the client configuration.

    mpsClientConfig* config;
    mpsStatus status = mpsruntime->createConfig(&config);
  7. Create the client context.

    mpsClientContext* context;
    status = mpsruntime->createContext(&context, config);
  8. Create the MATLAB data to input to the function.

    double a1[2][3] = {{1,2,3},{3,2,1}};
    double a2[2][3] = {{4,5,6},{6,5,4}};
    
    int numIn=2;
    mpsArray** inVal = new mpsArray* [numIn];
    
    inVal[0] = mpsCreateDoubleMatrix(2,3,mpsREAL);
    inVal[1] = mpsCreateDoubleMatrix(2,3,mpsREAL);
    
    double* data1 = (double *)( mpsGetData(inVal[0]) );
    double* data2 = (double *)( mpsGetData(inVal[1]) );
    
    for(int i=0; i<2; i++)
    {
      for(int j=0; j<3; j++)
      {
        mpsIndex subs[] = { i, j };
        mpsIndex id = mpsCalcSingleSubscript(inVal[0], 2, subs);
        data1[id] = a1[i][j];
        data2[id] = a2[i][j];
      }
    }
    
  9. Create the MATLAB data to hold the output.

    int numOut = 1;
    mpsArray **outVal = new mpsArray* [numOut];
  10. Call the deployed MATLAB function.

    Specify the following as arguments:

    • client context

    • URL of the function

    • Number of expected outputs

    • Pointer to the mpsArray holding the outputs

    • Number of inputs

    • Pointer to the mpsArray holding the inputs

    mpsStatus status = mpsruntime->feval(context,
        "http://localhost:9910/addmatrix/addmatrix",
        numOut, outVal, numIn, (const mpsArray**)inVal);
    

    For more information about the feval function, see the reference material included in the matlabroot/toolbox/compiler_sdk/mps_client folder.

  11. Verify that the function call was successful using an if statement.

    if (status==MPS_OK)
    {
    }
    
  12. Inside the if statement, add code to process the output.

    double* out = mpsGetPr(outVal[0]);
    
    for (int i=0; i<2; i++)
    {
      for (int j=0; j<3; j++)
      {        
        mpsIndex subs[] = {i, j};
        mpsIndex id = mpsCalcSingleSubscript(outVal[0], 2, subs);
        std::cout << out[id] << "\t";
      }
      std::cout << std::endl;
    }
  13. Add an else clause to the if statement to process any errors.

    else  
    {
      mpsErrorInfo error;
      mpsruntime->getLastErrorInfo(context, &error);
      std::cout << "Error: " << error.message << std::endl;
      switch(error.type)
      {
        case MPS_HTTP_ERROR_INFO:
          std::cout << "HTTP: " << error.details.http.responseCode << ": " 
              << error.details.http.responseMessage << std::endl;
        case MPS_MATLAB_ERROR_INFO:
          std::cout << "MATLAB: " << error.details.matlab.identifier 
              << std::endl;
          std::cout << error.details.matlab.message << std::endl;
        case MPS_GENERIC_ERROR_INFO:
          std::cout << "Generic: " << error.details.general.genericErrorMsg 
              << std::endl;
      }
    
      mpsruntime->destroyLastErrorInfo(&error);
    }
  14. Free the memory used by the inputs.

    for (int i=0; i<numIn; i++)
      mpsDestroyArray(inVal[i]);
    delete[] inVal;
    
  15. Free the memory used by the outputs.

    for (int i=0; i<numOut; i++)
      mpsDestroyArray(outVal[i]);
    delete[] outVal;
    
  16. Free the memory used by the client runtime.

    mpsruntime->destroyConfig(config);
    mpsruntime->destroyContext(context);
    mpsTerminate();
    
  17. Save the file.

    The completed program should resemble the following:

    #include <iostream>
    #include <mps/client.h>
    
    int main ( void )
    {
      mpsClientRuntime* mpsruntime = mpsInitializeEx(MPS_CLIENT_1_1);
    
      mpsClientConfig* config;
      mpsStatus status = mpsruntime->createConfig(&config);
    
      mpsClientContext* context;
      status = mpsruntime->createContext(&context, config);
    
      double a1[2][3] = {{1,2,3},{3,2,1}};
      double a2[2][3] = {{4,5,6},{6,5,4}};
    
      int numIn=2;
      mpsArray** inVal = new mpsArray* [numIn];
      inVal[0] = mpsCreateDoubleMatrix(2,3,mpsREAL);
      inVal[1] = mpsCreateDoubleMatrix(2,3,mpsREAL);
      double* data1 = (double *)( mpsGetData(inVal[0]) );
      double* data2 = (double *)( mpsGetData(inVal[1]) );
      for(int i=0; i<2; i++)
      {
        for(int j=0; j<3; j++)
        {
          mpsIndex subs[] = { i, j };
          mpsIndex id = mpsCalcSingleSubscript(inVal[0], 2, subs);
          data1[id] = a1[i][j];
          data2[id] = a2[i][j];
        }
      }
    
      int numOut = 1;
      mpsArray **outVal = new mpsArray* [numOut];
    
      status = mpsruntime->feval(context,
                   "http://localhost:9910/addmatrix/addmatrix",
                   numOut, outVal, numIn, (const mpsArray **)inVal);
    
      if (status==MPS_OK)
      {
        double* out = mpsGetPr(outVal[0]);
    
        for (int i=0; i<2; i++)
        {
          for (int j=0; j<3; j++)
          {
            mpsIndex subs[] = {i, j};
            mpsIndex id = mpsCalcSingleSubscript(outVal[0], 2, subs);
            std::cout << out[id] << "\t";
          }
          std::cout << std::endl;
        }
      }
      else
      {
        mpsErrorInfo error;
        mpsruntime->getLastErrorInfo(context, &error);
        std::cout << "Error: " << error.message << std::endl;
    
        switch(error.type)
        {
        case MPS_HTTP_ERROR_INFO:
          std::cout << "HTTP: " 
              << error.details.http.responseCode 
              << ": " << error.details.http.responseMessage
              << std::endl;
        case MPS_MATLAB_ERROR_INFO:
          std::cout << "MATLAB: " << error.details.matlab.identifier 
              << std::endl;
          std::cout << error.details.matlab.message << std::endl;
        case MPS_GENERIC_ERROR_INFO:
          std::cout << "Generic: " 
              << error.details.general.genericErrorMsg 
              << std::endl;
        }
        mpsruntime->destroyLastErrorInfo(&error);
      }
    
      for (int i=0; i<numIn; i++)
        mpsDestroyArray(inVal[i]);
      delete[] inVal;
    
      for (int i=0; i<numOut; i++)
        mpsDestroyArray(outVal[i]);
      delete[] outVal;
    
      mpsruntime->destroyConfig(config);
      mpsruntime->destroyContext(context);
      mpsTerminate();
    }
  18. Compile the application.

    To compile your client code, the compiler needs access to client.h. This header file is stored in matlabroot/toolbox/compiler_sdk/mps_client/c/include/mps/.

    To link your application, the linker needs access to the following files stored in matlabroot/toolbox/compiler_sdk/mps_client/c/:

    Files Required for Linking

    Windows® UNIX®/Linux Mac OS X
    $arch\lib\mpsclient.lib $arch/lib/libprotobuf.so $arch/lib/libprotobuf.dylib
     $arch/lib/libcurl.so $arch/lib/libcurl.dylib
     $arch/lib/libmwmpsclient.so $arch/lib/libmwmpsclient.dylib
     $arch/lib/libmwcpp11compat.so  
  19. Run the application.

    To run your application, add the following files stored in matlabroot/toolbox/compiler_sdk/mps_client/c/ to the application’s path:

    Files Required for Running

    Windows UNIX/Linux Mac OS X
    $arch\lib\mpsclient.dll$arch/lib/libprotobuf.so $arch/lib/libprotobuf.dylib
    $arch\lib\libprotobuf.dll$arch/lib/libcurl.so $arch/lib/libcurl.dylib
    $arch\lib\libcurl.dll$arch/lib/libmwmpsclient.so $arch/lib/libmwmpsclient.dylib
     $arch/lib/libmwcpp11compat.so  

    The client invokes addmatrix function on the server instance and returns the following matrix at the console:

    5.0 7.0 9.0
    9.0 7.0 5.0