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 (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_INSTALL
is 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
mpsArray
holding the outputsNumber 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
folder, where$MPS_INSTALL
/client$MPS_INSTALL
is the name of your MATLAB Production Server installation folder.Verify that the function call was successful using an
if
statement.if (status==MPS_OK) { }
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; }
Add an
else
clause to theif
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); }
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.so
Run 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.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