Main Content

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 Deploy Archive to MATLAB Production Server (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_clients/c/include/mps 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_clients 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_clients/c/include/mps/.

    To link your application, the linker needs access to the following files stored in matlabroot/toolbox/compiler_sdk/mps_clients/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_clients/c/ to the application’s path:

    Files Required for Running

    WindowsUNIX/LinuxMac 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