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 Create MATLAB Production Server Archive Using Production Server Archive Compiler App (MATLAB Compiler SDK)
and deployed in Deploy Archive to MATLAB Production Server.
Create a C++ MATLAB Production Server client application:
Create a file called
addmatrix_client.cpp.Using a text editor, open
addmatrix_client.cpp.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
folder where$MPS_INSTALL/client/c/include/mps$MPS_INSTALLis the root folder which MATLAB Production Server is installed.Add the
main()method to the application.int main ( void ) { }Initialize the client runtime.
mpsClientRuntime* mpsruntime = mpsInitializeEx(MPS_CLIENT_1_1);
Create the client configuration.
mpsClientConfig* config; mpsStatus status = mpsruntime->createConfig(&config);
Create the client context.
mpsClientContext* context; status = mpsruntime->createContext(&context, config);
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]; } }Create the MATLAB data to hold the output.
int numOut = 1; mpsArray **outVal = new mpsArray* [numOut];
Call the deployed MATLAB function.
Specify the following as arguments:
client context
URL of the function
Number of expected outputs
Pointer to the
mpsArrayholding the outputsNumber of inputs
Pointer to the
mpsArrayholding the inputs
mpsStatus status = mpsruntime->feval(context, "http://localhost:9910/addmatrix/addmatrix", numOut, outVal, numIn, (const mpsArray**)inVal);For more information about the
fevalfunction, see the reference material included in thefolder, where$MPS_INSTALL/client$MPS_INSTALLis the name of your MATLAB Production Server installation folder.Verify that the function call was successful using an
ifstatement.if (status==MPS_OK) { }Inside the
ifstatement, 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; }Add an
elseclause to theifstatement 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); }Free the memory used by the inputs.
for (int i=0; i<numIn; i++) mpsDestroyArray(inVal[i]); delete[] inVal;
Free the memory used by the outputs.
for (int i=0; i<numOut; i++) mpsDestroyArray(outVal[i]); delete[] outVal;
Free the memory used by the client runtime.
mpsruntime->destroyConfig(config); mpsruntime->destroyContext(context); mpsTerminate();
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(); }Compile the application.
To compile your client code, the compiler needs access to
client.h. This header file is stored in$MPSROOT/client/c/include/mps/.To link your application, the linker needs access to the following files stored in
$MPSROOT/client/c/<arch>/lib/:Files Required for Linking
Windows® UNIX®/Linux Mac OS X $arch\lib\mpsclient.lib$arch/lib/libprotobuf3.so$arch/lib/libprotobuf3.dylib$arch/lib/libcurl.so$arch/lib/libcurl.dylib$arch/lib/libmwmpsclient.so$arch/lib/libmwmpsclient.dylib$arch/lib/libmwcpp11compat.soRun the application.
To run your application, add the following files stored in
$MPSROOT/client/c/<arch>/lib/to the application’s path:Files Required for Running
Windows UNIX/Linux Mac OS X $arch\lib\mpsclient.dll$arch/lib/libprotobuf3.so$arch/lib/libprotobuf3.dylib$arch\lib\libprotobuf3.dll$arch/lib/libcurl.so$arch/lib/libcurl.dylib$arch\lib\libcurl.dll$arch/lib/libmwmpsclient.so$arch/lib/libmwmpsclient.dylib$arch/lib/libmwcpp11compat.soThe client invokes
addmatrixfunction on the server instance and returns the following matrix at the console:5.0 7.0 9.0 9.0 7.0 5.0