Access Remotable .NET Assembly Using Native .NET API: Cell and Struct
Why Use the .NET API with Cell Arrays and Structs?
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 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
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.
Building Your Component
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 using the instructions in Create Remotable .NET Assembly.
The Native .NET Cell and Struct Example
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.dllSelect 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 fileNativeStructCellServer.cs
:This code reads the associated configuration file to determine: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.
Coding and Building the Client Application and Configuration File
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.dllChange the references for the generated interface assembly to
.component_name
\for_redistribution_files_only\Icomponent_name
Native.dllSelect the appropriate build platform.
Select Debug or Release mode.
Build the
NativeStructCellClient
project.Supply the configuration file for the
NativeStructCellClient
.
NativeStructCellClient Code
The C# code for the client is in the file
NativeStructCellClient\NativeStructCellClient.cs
:
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
methodFrom this point, the remoting client calls methods on the remotable component exactly as it would call a local component method.
NativeStructCellClient Configuration File
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 numberMessage formatter (
binary
) and the permissions for the communication channel (full
trust)
Starting the Server Application
Start the server by doing the following:
Open a DOS or UNIX® command window and navigate 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] ##################################
Starting the Client Application
Start the client by doing the following:
Open a DOS or UNIX command window and navigate to
NativeStructCellClient\bin\x86\v4.0\Debug
.Run
NativeStructCellClient.exe
. After 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 #################################
Coding and Building the Client Application and Configuration File with the Native MWArray, MWStructArray, and MWCellArray Classes
createEmptyStruct.m
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');
updateField.m
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');
NativeStructCellClient.cs
Create the client C# code:
Note
In this case, you do not need 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(); } } }
NativeStructCellServer.cs
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(); } } }