Using .NET representations of MATLAB® struct and cell arrays is recommended if both of these are true:
You have MATLAB functions on a server with MATLAB struct or cell data types as inputs or outputs
You do not want or need to install a MATLAB Runtime on your client machines
The native MWArray
, MWStructArray
,
and MWCellArray
classes are members of the MathWorks.MATLAB.NET.Arrays.native
namespace.
The class names in this namespace are identical to the class
names in MathWorks.MATLAB.NET.Arrays
. The difference
is that the native representations of struct and cell arrays have
no methods or properties that require a MATLAB Runtime.
The
folder
has example solutions you can practice building. The matlabroot
\toolbox\dotnetbuilder\Examples\VSVersion
\NETNativeStructCellExample
folder
contains native struct and cell examples.
This example demonstrates how to deploy a remotable component using native struct and cell arrays. Before you set up the remotable client and server code, build a remotable component.
If you have not yet built the component you want to deploy, see the instructions in Building a Remotable Component Using the Library Compiler App or Building a Remotable Component Using the mcc Command.
The server application hosts the remote component.
The client application, running in a separate process, accesses
the remote component hosted by the server application. Build the server
with the Microsoft®
Visual Studio® project file NativeStructCellServer.csproj
:
Change the references for the generated component
assembly to
.component_name
\for_redistribution_files_only\component_name
Native.dll
Select the appropriate build platform.
Select Debug or Release mode.
Build the NativeStructCellServer
project.
Supply the configuration file for the NativeStructCellServer
.
The C# code for the server is in the file NativeStructCellServer.cs
:
using System; using System.Collections.Generic; using System.Text; using System.Runtime.Remoting; namespace NativeStructCellServer { class NativeStructCellServer { static void Main(string[] args) { RemotingConfiguration.Configure( @"NativeStructCellServer.exe.config"); Console.WriteLine("NativeStructCell Server started..."); Console.ReadLine(); } } }
Name of the component to host
Remoting protocol and message formatting to use
Lease time for the remote component
In addition, the code also signals that the server is active and waits for a carriage return before terminating.
The client application, running in a separate process, accesses
the remote component running in the server application built in The Native .NET Cell and Struct Example.
Build the remote client using the Microsoft
Visual Studio project
file NativeStructCellClient\NativeStructCellClient.csproj
.
To create the remote client using Microsoft
Visual Studio:
Change the references for the generated component
assembly to
.component_name
\for_redistribution_files_only\component_name
Native.dll
Change the references for the generated interface
assembly to
.component_name
\for_redistribution_files_only\Icomponent_name
Native.dll
Select the appropriate build platform.
Select Debug or Release mode.
Build the NativeStructCellClient
project.
Supply the configuration file for the NativeStructCellClient
.
The C# code for the client is in the file NativeStructCellClient\NativeStructCellClient.cs
:
using System; using System.Collections.Generic; using System.Text; using System.Runtime.Remoting; using System.Configuration; using MathWorks.MATLAB.NET.Arrays.native; using INativeStructCellCompNative; // This is a simple example that demonstrates the use // of MathWorks.MATLAB.NET.Arrays.native package. namespace NativeStructCellClient { class NativeStructCellClient { static void Main(string[] args) { try { RemotingConfiguration.Configure( @"NativeStructCellClient.exe.config"); String urlServer = ConfigurationSettings.AppSettings["NativeStructCellServer"]; INativeStructCellClassNative nativeStructCell = (INativeStructCellClassNative)Activator.GetObject(typeof (INativeStructCellClassNative), urlServer); MWCellArray field_names = new MWCellArray(1, 2); field_names[1, 1] = "Name"; field_names[1, 2] = "Address"; Object[] o = nativeStructCell.createEmptyStruct(1,field_names); MWStructArray S1 = (MWStructArray)o[0]; Console.WriteLine("\nEVENT 2: Initialized structure as received in client applications:\n\n{0}" , S1); //Convert "Name" value from char[,] to a string since there's no MWCharArray constructor on server that accepts //char[,] as input. char c = ((char[,])S1["Name"])[0, 0]; S1["Name"] = c.ToString(); MWStructArray address = new MWStructArray(new int[] { 1, 1 }, new String[] { "Street", "City", "State", "Zip" }); address["Street", 1] = "3, Apple Hill Drive"; address["City", 1] = "Natick"; address["State", 1] = "MA"; address["Zip", 1] = "01760"; Console.WriteLine("\nUpdating the 'Address' field to :\n\n{0}", address); Console.WriteLine("\n#################################\n"); S1["Address",1] = address; Object[] o1 = nativeStructCell.updateField(1, S1, "Name"); MWStructArray S2 = (MWStructArray)o1[0]; Console.WriteLine("\nEVENT 5: Final structure as received by client:\n\n{0}" , S2); Console.WriteLine("\nAddress field: \n\n{0}" , S2["Address",1]); Console.WriteLine("\n#################################\n"); } catch (Exception exception) { Console.WriteLine(exception.Message); } Console.ReadLine(); } } }
This code does the following:
The client reads the associated configuration file to get the name and location of the remotable component.
The client instantiates the remotable object using
the static Activator.GetObject
method
From this point, the remoting client calls methods on the remotable component exactly as it would call a local component method.
The configuration file for the NativeStructCellClient
is
in the file NativeStructCellClient\NativeStructCellClient.exe.config
:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="NativeStructCellServer" value= "tcp://localhost:1236/NativeStructCellClass.remote"/> </appSettings> <system.runtime.remoting> <application> <channels> <channel name="NativeStructCellChannel" ref="tcp" port="0"> <clientProviders> <formatter ref="binary" /> </clientProviders> <serverProviders> <formatter ref="binary" typeFilterLevel="Full" /> </serverProviders> </channel> </channels> </application> </system.runtime.remoting> </configuration>
This code specifies:
Name of the remote component server and the remote component URI (uniform resource identifier)
Remoting protocol (TCP/IP
) and
port number
Message formatter (binary
) and
the permissions for the communication channel (full
trust)
Start the server by doing the following:
Open a DOS or UNIX® command window and cd
to NativeStructCellServer\bin\x86\v4.0\Debug
.
Run NativeStructCellServer.exe
.
The following output appears:
EVENT 1: Initializing the structure on server and sending it to client: Initialized empty structure: Name: ' ' Address: [] ################################## EVENT 3: Partially initialized structure as received by server: Name: ' ' Address: [1x1 struct] Address field as initialized from the client: Street: '3, Apple Hill Drive' City: 'Natick' State: 'MA' Zip: '01760' ################################## EVENT 4: Updating 'Name' field before sending the structure back to the client: Name: 'The MathWorks' Address: [1x1 struct] ##################################
Start the client by doing the following:
Open a DOS or UNIX command window and cd
to NativeStructCellClient\bin\x86\v4.0\Debug
.
Run NativeStructCellClient.exe
.
After the MATLAB Runtime initializes, the following output appears:
EVENT 2: Initialized structure as received in client applications: 1x1 struct array with fields: Name Address Updating the 'Address' field to : 1x1 struct array with fields: Street City State Zip ################################# EVENT 5: Final structure as received by client: 1x1 struct array with fields: Name Address Address field: 1x1 struct array with fields: Street City State Zip #################################
Initialize the structure on the server and send it to the client with the following MATLAB code:
function PartialStruct = createEmptyStruct(field_names) fprintf('EVENT 1: Initializing the structure on server and sending it to client:\n'); PartialStruct = struct(field_names{1},' ',field_names{2},[]); fprintf(' Initialized empty structure:\n\n'); disp(PartialStruct); fprintf('\n##################################\n');
Receive the partially updated structure from the client and add more data to it, before passing it back to the client, with the following MATLAB code:
function FinalStruct = updateField(st,field_name) fprintf('\nEVENT 3: Partially initialized structure as received by server:\n\n'); disp(st); fprintf('Address field as initialized from the client:\n\n'); disp(st.Address); fprintf('##################################\n'); fprintf(['\nEVENT 4: Updating ''', field_name, ''' field before sending the structure back to the client:\n\n']); st.(field_name) = 'The MathWorks'; FinalStruct = st; disp(FinalStruct); fprintf('\n##################################\n');
Create the client C# code:
Note
In this case, you do not need the MATLAB Runtime on the system path.
using System; using System.Collections.Generic; using System.Text; using System.Runtime.Remoting; using System.Configuration; using MathWorks.MATLAB.NET.Arrays.native; using INativeStructCellCompNative; // This is a simple example that demonstrates the use of // MathWorks.MATLAB.NET.Arrays.native package. namespace NativeStructCellClient { class NativeStructCellClient { static void Main(string[] args) { try { RemotingConfiguration.Configure (@"NativeStructCellClient.exe.config"); String urlServer = ConfigurationSettings.AppSettings[ "NativeStructCellServer"]; INativeStructCellClassNative nativeStructCell = (INativeStructCellClassNative)Activator.GetObject(typeof (INativeStructCellClassNative), urlServer); MWCellArray field_names = new MWCellArray(1, 2); field_names[1, 1] = "Name"; field_names[1, 2] = "Address"; Object[] o = nativeStructCell.createEmptyStruct(1,field_names); MWStructArray S1 = (MWStructArray)o[0]; Console.WriteLine("\nEVENT 2: Initialized structure as received in client applications:\n\n{0}" , S1); //Convert "Name" value from char[,] to a string since // there's no MWCharArray constructor // on server that accepts char[,] as input. char c = ((char[,])S1["Name"])[0, 0]; S1["Name"] = c.ToString(); MWStructArray address = want new MWStructArray(new int[] { 1, 1 }, new String[] { "Street", "City", "State", "Zip" }); address["Street", 1] = "3, Apple Hill Drive"; address["City", 1] = "Natick"; address["State", 1] = "MA"; address["Zip", 1] = "01760"; Console.WriteLine("\nUpdating the 'Address' field to :\n\n{0}", address); Console.WriteLine("\n#################################\n"); S1["Address",1] = address; Object[] o1 = nativeStructCell.updateField(1, S1, "Name"); MWStructArray S2 = (MWStructArray)o1[0]; Console.WriteLine("\nEVENT 5: Final structure as received by client:\n\n{0}" , S2); Console.WriteLine("\nAddress field: \n\n{0}" , S2["Address",1]); Console.WriteLine("\n#################################\n"); } catch (Exception exception) { Console.WriteLine(exception.Message); } Console.ReadLine(); } } }
Create the server C# code:
using System; using System.Collections.Generic; using System.Text; using System.Runtime.Remoting; namespace NativeStructCellServer { class NativeStructCellServer { static void Main(string[] args) { RemotingConfiguration.Configure( @"NativeStructCellServer.exe.config"); Console.WriteLine("NativeStructCell Server started..."); Console.ReadLine(); } } }