=======================
HOOPS for C# Developers
=======================

Introduction
============

.. only:: standard

	HOOPS C# supports consists of C# wrappers to HOOPS/3DGS, HOOPS/MVO, HOOPS/Stream, and HOOPS/Parasolid. This guide discusses specific language features associated with developing with HOOPS in C#. Some familiarity with HOOPS/3DGS and HOOPS/MVO is assumed.

.. only:: spatial

	HOOPS C# supports consists of C# wrappers to HOOPS/3DGS, HOOPS/MVO, and HOOPS/Stream. This guide discusses specific language features associated with developing with HOOPS in C#. Some familiarity with HOOPS/3DGS and HOOPS/MVO is assumed.

For developers who want to integrate HOOPS with C# GUI toolkits like Winforms and WPF, documentation is provided in the :doc:`HOOPS/Winforms </prog_guide/misc/winforms_integration>` and :doc:`HOOPS/WPF </prog_guide/misc/wpf_integration>` documentation,  respectively.

Please see the release notes for information regarding the required version of the .NET framework.


Compilation and Execution
=========================

The following steps are required to compile and run a C# based application:
	
**Compiling**: Your application must reference the HOOPS/3DF C# wrapper classes.

.. only:: standard

	.. raw:: html

		<ul>
			<li>All 3DGS applications:</li>
				<ul>
					<li><em>hoops&lt;version&gt;_cs&lt;Visual Studio version&gt;.dll</em></li>
					<li><em>hics&lt;version&gt;_cs&lt;Visual Studio version&gt;.dll</em></li>
				</ul>
			

			<li>Applications using HOOPS/MVO:</li>
				<ul>
					<li>hoops_mvo&lt;version&gt;_cs&lt;Visual Studio version&gt;.dll.</li>
				</ul>
			
			
			<li>Applications using HOOPS/Stream:</li>
				<ul>
					<li><em>hoops_stream&lt;version&gt;_cs&lt;Visual Studio version&gt;.dll.</em></li>
				</ul>

			<li>Applications using HOOPS/Parasolid:</li>
				<ul>
					<li><em>hcsp_bridge&lt;version&gt;_cs90.dll.</em>. Note that the Parasolid Bridge is only supported for Microsoft Visual Studio 2008 (VC 9).</i></li>
				</ul>
		</ul>
		
.. only:: spatial

	.. raw:: html

		<ul>
			<li>All 3DGS applications:</li>
				<ul>
					<li><em>hoops&lt;version&gt;_cs&lt;Visual Studio version&gt;.dll</em></li>
					<li><em>hics&lt;version&gt;_cs&lt;Visual Studio version&gt;.dll</em></li>
				</ul>
			

			<li>Applications using HOOPS/MVO:</li>
				<ul>
					<li>hoops_mvo&lt;version&gt;_cs&lt;Visual Studio version&gt;.dll.</li>
				</ul>
			
			
			<li>Applications using HOOPS/Stream:</li>
				<ul>
					<li><em>hoops_stream&lt;version&gt;_cs&lt;Visual Studio version&gt;.dll.</em></li>
				</ul>
		</ul>	
		
**Executing**: Ensure that the following native DLLs are in your application's directory or in your ``PATH``.

.. only:: standard
		
	.. raw:: html		

		<ul>
			<li>All 3DGS applications:</li>
				<ul>
					<li><em>hoops&lt;version&gt;_vc&lt;Visual Studio version&gt;.dll</em></li>
					<li><em>hcs&lt;version&gt;.dll</em></li>
					<li><em>hics&lt;version&gt;.dll</em></li>
				</ul>
			
			<li>Applications using HOOPS/MVO:</li>
				<ul>
					<li><em>hoops_mvo_mgk&lt;version&gt;_vc&lt;Visual Studio version&gt;.dll</em></li>
					<li><em>hcsmvo&lt;version&gt;.dll</em></li>
				</ul>
				
				<li>Applications using HOOPS/Stream:</li>
					<ul>
						<li><em>hoops_stream&lt;version&gt;_vc&lt;Visual Studio version&gt;.dll</em></li>
						<li><em>hcsstream&lt;version&gt;.dll</em></li>
					</ul>
				
					<li>Applications using HOOPS/Parasolid:<i>Note that the Parasolid Bridge is only supported for Microsoft Visual Studio 2008 (VC 9).</i></li>
						<ul>
							<li><em>hp_bridge&lt;version&gt;_&lt;Parasolid version&gt;_vc90.dll</em></li>
							<li><em>hcsp_bridge&lt;version&gt;.dll</em></li>
							<li><em>pskernel.dll</em></li>
							<li><em>pskernel_net.dll</em></li>
						</ul>
					
				</ul>
			
		</ul>

.. only:: spatial

	.. raw:: html
	
		<ul>
			<li>All 3DGS applications:</li>
				<ul>
					<li><em>hoops&lt;version&gt;_vc&lt;Visual Studio version&gt;.dll</em></li>
					<li><em>hcs&lt;version&gt;.dll</em></li>
					<li><em>hics&lt;version&gt;.dll</em></li>
				</ul>
			
			<li>Applications using HOOPS/MVO:</li>
				<ul>
					<li><em>hoops_mvo_mgk&lt;version&gt;_vc&lt;Visual Studio version&gt;.dll</em></li>
					<li><em>hcsmvo&lt;version&gt;.dll</em></li>
				</ul>
				
				<li>Applications using HOOPS/Stream:</li>
					<ul>
						<li><em>hoops_stream&lt;version&gt;_vc&lt;Visual Studio version&gt;.dll</em></li>
						<li><em>hcsstream&lt;version&gt;.dll</em></li>
					</ul>
				
				</ul>
			
		</ul>

The above files are located in your *<hoops>/bin/nt_<platform>_vc<Visual Studio version>* directory.


Strong-Named Assemblies
=======================

As described in `this link <http://msdn.microsoft.com/en-us/library/xwb8f617.aspx>`_, we create our .NET assemblies as "Strong-Named Assemblies". Advantages:

* Strong-named assemblies contain public key and digital signature (created with the TS3D private signing key). The public key combined with the assembly name/version allow an application to uniquily reference a strong-named assembly; this is similar to a GUID, and hence the name "strong-named". Additionally, the public key combined with the digital signature allows the .NET runtime to verify that the DLL bits were not tampered with (ie, modified).
* Strong-named assemblies can be placed in the global assembly cache (GAC)
* Customer built strong-named assemblies can reference HOOPS/3DF strong-named assemblies

Tech Soft 3D keeps a private copy of the signing key generated by the Microsoft *sn.exe* tool. However, the affected strong-named assembly projects all reference this signing key. Customers can provide their own strong name key *.snk* file if they need to re-build any Tech Soft 3D strong-named assembly. If they do not provide one, a custom pre-build event is in place which will auto-generate a new random *.snk* file. 

The projects expect the *.snk* file to be at the top-level HOOPS/3DF directory with the name *signing_key.snk*: *$(HOOPS_INSTALL_DIR)/signing_key.snk*.


Interface Notes: General Usage
==============================

The routines and classes of the HOOPS/3DGS, HOOPS/MVO and HOOPS/Stream toolkits are all generally accessible via the C# wrappers, with a few exceptions and notes covered below. Developers should refer to the API reference manual for each component, and can additionally leverage the Intellisense capability of Visual Studio  to dynamically access listings of class members and function/method argument while programming.


Defines
-------

You should also add this "define" to your document somewhere::

	#if _M_X64
	  using HLONG = System.Int64;
	#else
	  using HLONG = System.Int32;
	#endif

Then, for 64 bit projects, you should define the ``_M_X64`` (you can name this anything you want). You should use ``HLONG`` in all places where you would normally use a C "long". This is because C#'s "long" is always 64 bit, whereas C's "long" is often 32 bit, and are incompatible. Using ``HLONG`` will help ensure compatability. (You can also simply use ints for 32 bit projects and longs for 64 bit projects, but things may get confusing).


HOOPS/3DGS-Specific
===================

Routine Prefixes
----------------

Each routine name, such as ``Insert_Polyline`` in your HOOPS program must have a prefix before the name will actually be usable on your computer system. The prefix varies depending on which language you're calling from, and sometimes depending on the brand of the language you're calling from. When calling from C#, all calls to the HOOPS/3DGS API are made through the HCS class, such as::

	HCS.Open_Segment("newsegment");
	HCS.Insert_Line(0, 0, 0, 1, 1, 1);
	HCS.Close_Segment();


HOOPS Routines Available in C#
------------------------------

Most functions available under C are available in C# except for: 


* ::Define_Callback_Name 
* ::Define_Exit_Handler
* ::UnDefine_Exit_Handler
* ::Define_Callback_Name
* ::UnDefine_Callback_Name
* ::Show_Callback_Name
  
Two functions are different under C# compared to C: 

* ::UnDefine_Error_Handler 
* ::Define_Error_Handler
* ::Find_Error_Handler 

Both take an ``HCSU.ErrorFunc`` object (which is a delegate) as their argument. If null is passed to ``UnDefine_Error_Handler``, it will remove the default HOOPS error handler. ``HCSU.ErrorFunc`` denotes error functions that take proper C# string arrays as arguments as opposed to ``unsafe`` C# pointers. If an already registered ``HCSU.ErrorFunc`` is passed, that handler will be removed. 
	
Here is an example of declaring an error handler::

	public void error_handler(int category, int specific, int severity, int msgc, sbyte ** msgv, int stackc, sbyte ** stackv)
	{
	}

	public void init()
	{  
		HCSU.ErrorFunc error_hndlr_ptr = new HCSU.ErrorFunc(error_handler);
		HCS.Define_Error_Handler(error_hndlr_ptr);
		
		HCS.Open_Segment("?picture");
		  //  do something
		HCS.Close_Segment();
	}

**NOTE:** You may have to set your project to "allow unsafe code" in order to use the error handler, as it uses pointers.


Multi-Threading
---------------

You must call ``Define_System_Options("multi-threading=full")`` as your first HOOPS call. This is because C# apps must be thought of as multi-threaded, since the garbage collector will run on a separate thread and may trigger HOOPS calls on a separate thread if it invokes certain destructors.


Pointers and Write-Back Values
------------------------------

The largest difference between using HOOPS with C# and C is found when you have a write-back value, i.e. you pass a pointer to a function and it writes a value or values to that location. In HOOPS C#, arrays can typically be written to without any extra help, while single variables need a "ref" keyword before the object name (similar to the \"&\" operator in C/C++).

For example, the C HOOPS code that uses a ``char*``::

	char ex[1024];
		
	HC_Show_Alias("?picture", ex);
	printf("?picture=%s\n", ex); 

is replaced in C# by ``StringBuilder``:: 

	StringBuilder ex = new StringBuilder(1024);

	HCS.Show_Alias("?picture", ex);

	Console.WriteLine("?picture="+ex);
	
**NOTE**: The "StringBuilder" type is used for write-back values. You should use the ``string`` type for constant string values. These are enforced by the function signatures, so you should not be able to pass in the wrong type.

The C HOOPS code that uses ``&[float_value]``::

	float x,y,z;

	HC_Open_Segment("?picture");     
	HC_Show_Camera_Position(&x, &y, &z);
	HC_Close_Segment();

	printf(" x=%f y=%f z=%f\n", x, y, z); 

...is used in a similar manner in C#, with the ``out`` keyword::

	float x = new float();
	float y = new float();
	float z = new float();

	HCS.Open_Segment("?picture");	
	HCS.Show_Camera_Position(out x, out y, out z); 
	HCS.Close_Segment();

	Console.WriteLine(" x="+ x + " y="+ y + " z="+ z); 

Arrays can be used in C# in a similar manner as they are used in C. The following C code::

	float v1[3] = {1.0f,0.0f,0.0f};
	float v2[3] = {0.0f,1.0f,0.0f};
	float v3[3];
		  
	HC_Compute_Cross_Product(v1,v2,v3);
	printf("%f %f %f\n", v3[0], v3[1], v3[2]); 

...is written in C# by::

	float[] v1 = {1.0f,0.0f,0.0f};
	float[] v2 = {0.0f,1.0f,0.0f};
	float[] v3 = new float[3];
	HCS.Compute_Cross_Product(v1,v2,v3);
	Console.WriteLine(v3[0] + " " + v3[1] + " " + v3[2]); 


HOOPS Keys
----------

Another difference between using HOOPS with C# and C is found when dealing with HOOPS keys. In C#, you should use ``HLONG`` (assuming you defined it as mentioned in the previous section). Thus, the C code::

	HC_KEY key = 0;

	key = HC_Open_Segment("?picture");
	// ...
	HC_Open_Segment_By_Key(key); 

...is replaced in C# by::

	HLONG key = 0;

	key = HCS.Open_Segment("?picture");
	// ...
	HCS.Open_Segment_By_Key(key); 


Datatype Names and Language Declarations in C#
----------------------------------------------

The C# datatypes translate as follows: 

.. raw:: html

    <table>
      <tr>
        <th>HOOPS</th>
        <th>HOOPS (HC) type</th>
        <th> C# type</th>
      </tr>
      <tr>
        <td>'string'</td>
        <td>const char *</td>
        <td>string</td>
      </tr>
      <tr>
        <td>'writes string'</td>
        <td> char *</td>
        <td>StringBuilder</td>
      </tr>
      <tr>
        <td>'string'</td>
        <td>unsigned short const *</td>
        <td>string</td>
      </tr>
      <tr>
        <td>'writes string'</td>
        <td>unsigned short *</td>
        <td>StringBuilder</td>
      </tr>
      <tr>
        <td>'HC_KEY'</td>
        <td>HC_KEY</td>
        <td>HLONG (System.Int32 / System.Int64)</td>
      </tr>
      <tr>
        <td>'int'</td>
        <td>int</td>
        <td>int</td>
      </tr>
      <tr>
        <td>'writes int'</td>
        <td>&int</td>
        <td>out int</td>
      </tr>
      <tr>
        <td>'float'</td>
        <td>float</td>
        <td>float</td>
      </tr>
      <tr>
        <td>'writes float'</td>
        <td>&float</td>
        <td>out float</td>
      </tr>
      <tr>
        <td>'point'</td>
        <td>float[3]</td>
        <td>float[3]</td>
      </tr>
      <tr>
        <td>'writes point'</td>
        <td>&float</td>
        <td>float[]</td>
      </tr>
      <tr>
        <td>'writes bytes'</td>
        <td>unsigned char *</td>
        <td>sbyte[]</td>
      </tr>
      <tr>
        <td>'writes ints'</td>
        <td>&int</td>
        <td>int[]</td>
      </tr>
    </table>


_By_Ref Routines
----------------

In general, users should not use these methods since HOOPS may end up holding a pointer to managed memory which may be de-allocated or relocated by the C# garbage collector.

If it is essential for you to use any ``_By_Ref`` variants, you must ensure that your memory is not affected by the garbage collector.  This can be achieved by using the C# ``fixed`` keyword, or by using ``GCHandle.Alloc``.
  
  
HOOPS Intermediate Mode
-----------------------

The HOOPS intermediate mode library provides a means for an application to trap the HOOPS update cycle at certain points in the rendering pipeline through a set of callback classes. When you trap the update cycle at a callback point, you can decide what and how something is drawn, or even abort the process itself. The HOOPS I.M. library also provides a set of functions you can call from your callback class to draw to the display in an "immediate mode" style and to query the graphics database and the device characteristics.  In the HOOPS/3dGS Programming Guide, you can learn more about :doc:`HOOPS I.M. </prog_guide/3dgs/08_1_im_overview>` and how to :ref:`implement and use the callback classes <prog_guide/3dgs/08_1_im_overview:Callbacks for C++/C#/Java Developers>`.


HOOPS/MVO and HOOPS/Stream
==========================

Protected Class Members
-----------------------

When using the C# wrappers, protected  members of a parent HOOPS/MVO or HOOPS/Stream class can be accessed just like any 
member from a child class.


Accessing overloaded Virtual Methods
------------------------------------

Support for overriding virtual methods of C#/Java classes is enabled via our use of a C++ wrapper-concept called 'directors'. Directors are currently only enabled for a subset of C#/Java classes. Developers can see which classes have directors enabled by examining the *directors.i* files at each of the following locations.

C#:

* *[HOOPS]\\Dev_Tools\\hoops_mvo\\source\\csharp_mvo\\*
* *[HOOPS]\\Dev_Tools\\hoops_stream\\source\\csharp_stream\\*
* *[HOOPS]\\Dev_Tools\\hoops_3dgs\\source\\csharp_im\\*

Java:

* *[HOOPS]\\Dev_Tools\\hoops_mvo\\source\\java_mvo\\*
* *[HOOPS]\\Dev_Tools\\hoops_stream\\source\\java_stream\\*
* *[HOOPS]\\Dev_Tools\\hoops_3dgs\\source\\java_im\\*


Garbage Collection and the ``Dispose`` Method
---------------------------------------------

In C#/Java, the garbage collector takes care of all the memory management for purely C# or Java objects, thus you don't need to explicitly clean them up. However, for native/unmanaged resources, such as the HOOPS C#/Java wrappers which wrap C++ objects (e.g. HOOPS/MVO and HOOPS/Stream objects, callback classes, etc...), the garbage collector may cleanup such objects, but will do so in an non-deterministic order.

For example, each time you create a C# ``HBaseView``, a C++ ``HBaseView`` is created. The C++ object stays until ``HBaseView.Dispose()`` is called, or until the garbage collector calls it for you. But due to dependencies, certain objects need to be destroyed before others. Another example is that ``HBaseView`` needs to be deleted before ``HBaseModel``, which should in turn be deleted before the ``HDB``.

**IMPORTANT:** C#/Java developers need to be aware that they must explicitly call ``Dispose()`` or ``delete()`` as if it were a C++ program, in order to trigger the C++ destructor. Additionally, objects should be destroyed in the reverse order they were created. (C#/Java developers who work with unmanaged resources/JNI may already be accustomed  to this).

On a related note, users cannot expect objects to stay around when passed as arguments to MVO/Stream functions, such as with a ``Set`` operation (for example, ``SetHandleOperator``). If the user does not manually store a reference to the object that was passed to the function in their application, then code may unexpectedly fail at times due to garbage collection. For example::

	// Incorrect way. Will cause unexpected garbage collection! It may appear that
	// view.SetCurrentOperator() holds a reference to the newly created 
	// HOpCreateSphere. In fact, it does have a handle to the underlying C++ object, 
	// but not to the C# proxy object.
	HBaseView view;
	view.SetCurrentOperator(new HOpCreateSphere(view));

	// Correct way.  We need to keep a handle to the C# proxy object for it to persist.
	// For this object, C# will automatically call the destructor when the object goes out of scope.
	m_pHPanel.SetCurrentOperator(new HOpCreateSphere(m_pHPanel.m_pHView));


Array Handling in C#
--------------------

*Notes on MVO/HStream/BStream/IM methods which return arrays*

* C++ methods which return arrays (as a return type) have corresponding methods in C# which return ``IntPtr``
* Each C# module (``HCSMVO``, ``HCSSTREAM``, ``HICS``) has three extract methods which must be used to obtain the C# array associated with the ``IntPtr``:

	* ``public static float[] ExtractFloatArray(IntPtr source, int count)``
	* ``public static int[] ExtractIntArray(IntPtr source, int count)``
	* ``public static T[] ExtractArray<T>(IntPtr source, int count)``

Example for ``HShellObject::GetFlist()``::

	public IntPtr GetFlist();

Sample usage::

	// let's assume that hso is a valid HshellObject
	int[] flist = HCSMVO.ExtractIntArray(hso.GetFlist(), hso.GetFlistLen());

*Notes on MVO/HStream/BStream/IM array member variables*

Array member variables are of type IntPtr and read-only::

	public IntPtr face_list{ get{…} }

Sample usage::

	// shell is a valid HShell object
	int[] flist = HCSMVO.ExtractIntArray(shell.face_list, shell.face_count);


``HFileInputResult`` and ``HFileOutputResult``
----------------------------------------------

C# users should use the enum HFileIOResult wherever HFileInputResult or HFileOutputResult are mentioned in our documentation. For example::

	HFileIOResult result = myView.GetModel().Read("c:/datasets/bnc.hsf", myView);

	if (result != HFileIOResult.HIO_OK)
	{
	  // ... error
	}


HOOPS/MVO Classes in C#/Java
----------------------------
  
A majority of HOOPS/MVO classes are available in C# and Java. However, a number of HOOPS/MVO classes are not provided due to  inherent limitations of creating C#/Java wrappers for C++ classes. HOOPS/MVO provides the ability create and modify animations.  The HOOPS/MVO animation classes that are accessible in C#/Java are ``HBhvAnimation`` and ``HBhvBehaviorManager``. These classes give you the ability to build and manipulate a wide variety of keyframe based behaviors as described in sections on :doc:`behaviors and animations </prog_guide/mvo/10_behavior_and_animation>` and :ref:`defining behaviors <prog_guide/mvo/10_behavior_and_animation:Defining behaviors>` in the HOOPS/MVO Programming Guide. The classes associated with animations that are not accessible in C#/Java include:
  
* ``HBhvInterpolator[type]``
* ``HBhvCondition[type]``
* ``HBhvAction``
* ``HBhvTimeline``
* ``HBhvUtility``
* ``TK_Bhv_XML``
 
A number of input and output handlers are not available in C#/Java. They include:

* ``HUtilityPMI`` - This class is wrapped in Java, but not in C#. Please see the :doc:`Java Programming Guide </general/language_java>` for usage details.
* ``HIOUtilityAVI``
* ``AVIExportInfo``
* ``HIOUtilityCGM``
* ``HIOUtilityHMF``
* ``HIOUtilityPostscript``
* ``HIOUtilityHPGL2``
* ``HIOUtilityPDF``
* ``HPDFOptions``
* ``HPDFPoster``
* ``HIOUtilityHsf``
* ``HIOUtilityHTML``
* ``HIOUtilityMagick``
* ``HIOUtilityObj``
* ``HIOUtilityPly``
* ``HIOUtilityStl``
* ``HIOUtilityVRML``
 
 
Multiple Inheritance
--------------------

The concept of multiple inheritance is not supported in C# or Java. Thus, access to HOOPS/MVO classes that utilize multiple inheritance is limited. Specifically, these classes were wrapped with only one class inherited. The following is a list of the C++ MVO classes that use multiple inheritance and what single class they now inherit from in C#/Java.

.. csv-table::
	:header: "HOOPS/MVO Class", "Parent Class in C#/Java", "Parent Classes in C++"
	
	"``HBaseView``", "``HUpdateListener``", "``HUpdateListener``, ``HMouseListener``, ``HObjectManipulationListener``"
	"``HTCObjectRotate``", "``HBaseOperator``", "``HBaseOperator``, ``HTClient``"
 
Additionally, the inability to inherit from multiple classes will impede the use of the ``HEventListener``, ``HEventListenerItem``, ``HEventListenerManager`` and ``HEventManager`` classes. When deriving a class from one of these event classes, it is likely that you will want to derive from another HOOPS/MVO class like HBaseOperator at the same time. Thus, the event classes cannot be used in this manner.
 
Note that pointers to ``vlist`` and ``vhash`` are also not accessible via C# or Java.   

.. only:: standard 

	HOOPS/Parasolid
	===============
	
	All the methods needed to use the HOOPS/Parasolid integration module are available in C#. You can read more about them in the HOOPS/Parasolid reference manual. In the C# interface for HOOPS/Parasolid, you will find that ``Read_Xmt_File`` and ``Write_Xmt_File`` are not included. For ``Read_Xmt_File``, we recommend that instead, you use the native Parasolid C# methods to load object into the Parsolid modeler. Once this is complete, then you import them into HOOPS.  The following sample code shows how you can do this::

		HFileInputResult Read_Xmt(string filename)
		{
		  PK.ERROR.code_t result;

		  PK.PART.receive_o_t options = new PK.PART.receive_o_t(true);
		  options.transmit_format = PK.transmit_format_t.text_c;

		  fixed( PK.PART_t **parts = &m_pParts )
		  fixed (int* num_parts = &m_numParts)
		  {
			 result = PK.PART.receive(filename, &options, num_parts, parts);
		  }            

		  if (result == PK.ERROR.code_t.no_errors)
		  {
			  HCS.Open_Segment_By_Key(this.GetModelKey());
				  HCSP.Render_Entities(m_numParts, (PK.ENTITY_t*)m_pParts, 0, null);
			  HCS.Close_Segment();
		  }

		  return (result == PK.ERROR.code_t.no_errors) ? HFileInputResult.InputOK : HFileInputResult.InputFail;
		}

	For ``Write_Xmt_File``, we recommend also that you use the native Parasolid C# methods to export information into a file. The following sample code shows how to write an XMT file::

		HFileOutputResult Write_Xmt(string filename)
		{
		  PK.ERROR.code_t result;

		  PK.PART.transmit_o_t options = new PK.PART.transmit_o_t(true);
		  options.transmit_format = PK.transmit_format_t.text_c;
					
		  result = PK.PART.transmit(m_numParts, m_pParts, filename, &options);            

		  return (result == PK.ERROR.code_t.no_errors) ? HFileOutputResult.OutputOK : HFileOutputResult.OutputFail;            
		}


	The ``Read_Xmt_File`` and ``Write_Xmt_File`` methods are used in C# sample programs that integrate with HOOPS/Parasolid.
