The HOOPS/Winforms integration consists of C# wrappers to HOOPS/3dGS, HOOPS/MVO, HOOPS/Stream and HOOPS/Parasolid . This document describes how to use C# with the different HOOPS/3dAF components. Some familiarity with HOOPS/3dGS and HOOPS/MVO is assumed. This guide discusses specific language features associated with developing with HOOPS in C#. For developers who want to integrate HOOPS with C# GUI toolkits like Winforms and WPF, documentation is provided in the HOOPS/Winforms and HOOPS/WPF, respectively.
The C# base HOOPS applications are supported under Microsoft Visual Studio 2005 (VC8) and Microsoft Visual Studio 2008 (VC9).
The following steps are required to compile and run a C# based application:
The above files are located in your <hoops>/bin/nt_i386_vc<Visual studio="" version>=""> directory.
Note: Both C#.Net and VB.Net application code can access these C# wrappers, because Visual Studio 2005 provides built in support for VB apps to access C# interfaces. You simply include the C# references.
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 Reference Manual for each component, and can additionally leverage the Intellisense capability of Visual Studio 2005 to dynamically access listings of class members and function/method argument while programming.
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).
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();
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
Set_Driver
QSet_Driver
Two functions are different under C# than C:
UnDefine_Error_Handler
Define_Error_Handler
Both take an HCSU.errfunc object (which is a delegate) as their argument. If null is passed to UnDefine_Error_Handler, it will remove the default HOOPS error handler. If an already registered HCSU.errfunc 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.errfunc error_hndlr_ptr = new HCSU.errfunc(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.
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 "&" 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); ex.EnsureCapacity(1024); HCS.Show_Alias("?picture", ex); Console.WriteLine("?picture="+ex);
NOTE: The "StringBuilder" type is used for write-back values. Note that before you begin writing into StringBuilder, you should call EnsureCapacity to guarantee your instance has the minimum specified value. 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_QShow_Camera_Position("?picture", &x, &y, &z); printf(" x=%f y=%f z=%f\n", x, y, z);
is used in a similar manner in C#, with the "ref" keyword:
float x = new float(); float y = new float(); float z = new float(); HCS.QShow_Camera_Position("?picture", ref x, ref y, ref z); Console.WriteLine(" x="+ x + " y="+ y + " z="+ z);
Arrays can be used in C# in a similar manner as they are used in C. Thus, the C HOOPS 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 accomplished 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]);
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 Section 3.1 above). 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.KOpen_Segment("?picture");
...
HCS.Open_Segment_By_Key(key);
The C# datatypes translate as follows:
| HOOPS | HOOPS (HC) type | C# type |
| 'string' | HC type | string |
| 'writes string' | const char * | StringBuilder |
| 'HC_KEY' | HC_KEY | HLONG (System.Int32 / System.Int64) |
| 'int' | int | int |
| 'writes int' | +" | ref int |
| 'float' | float | float |
| 'writes float' | &float | ref float |
| 'point' | float[3] | float[3] |
| 'writes point' | &float | float[] |
| 'writes bytes' | unsigned char * | sbyte[] |
| 'writes ints' | +" | int[] |
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 HOOPS I.M. and how to implement and use the callback classes.
Prior to Release 17, when developers derived from a HOOPS/MVO class in C#, they could not access protect members. However beginning with Release 17, protected members of a parent HOOPS/MVO class can be accessed just like any member from a child class. For Java developers, protected members are accessed via helper set/get functions with member name appended to the end of set/get.
A majority of HOOPS/MVO classes are available in C# and Java. However, a number of HOOPS/MVO classes are not provided due to some inherent challenges with the wrapper process.
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 10.1 Introduction to Behaviors and Animations to 10.3 Defining Behaviors for basic animations in the HOOPS/MVO Programming Guide. The classes associated with animation that not accessible in C# are listed below.
The following operators are also not accessible in C#/Java:
A number of input and output handlers are not available in C#/Java. They are listed below.
Although HObject and HObjectManager are both availabe in C#/Java, the HOOPS/MVO child classes associated with HObject are not. These include the following:
Most utility classes are available in C#/Java except for the following:
The following HOOPS/MVO classes are also not accessible via C#/Java:
The concept of multiple inheritance is not supported in C# or Java. Thus, access to certain 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.
| 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.
Most HOOPS/MVO datatypes are accessible in C#/Java but there are some datatypes that have not gone through the wrapper process. They appear in the C#/Java environment with the SWIGTYPE prefixed to their datatype name. Although methods that use these datatypes can be seen with Intellisense, any code calling these methods will not compile. Below is a list of methods that cannot be called in C#/Java because they used datatypes that have not gone through the wrapper process completely.
| HOOPS/MVO Class | Inaccessible HOOPS/MVO Method |
| HAnimationListener | public virtual int ObjectCollisionEvent(SWIGTYPE_p_HBhvTargetObject tob) |
| HAnimationListener | public virtual int ObjectNoCollisionEvent(SWIGTYPE_p_HBhvTargetObject tob) |
| HAnimationListener | public virtual int AnimationFinishedEvent(SWIGTYPE_p_HBhvAnimation ainst) |
| HBaseModel | public SWIGTYPE_p_HBhvBehaviorManager GetBhvBehaviorManager() |
| HBaseModel | public void SetBhvBehaviorManager(SWIGTYPE_p_HBhvBehaviorManager BehaviorManager) |
| HBaseView | public bool SetStencilProbe(SWIGTYPE_p_HStencilProbe sp) |
| HBaseView | public SWIGTYPE_p_HUtilityAntialiasing GetAntialiasing() |
| HBaseView | public SWIGTYPE_p_HStencilProbe GetStencilProbe() |
| HBaseView | public SWIGTYPE_p_HSharedKey GetSharedKey() |
| HDebugZBuffer | public void OpenglFinishPicture(SWIGTYPE_p_ht_net_rendition nr, bool swap_buffers) |
| HImErrorHandler | public static void CallbackEntryPoint(int category, int specific, int severity, int msgc, SWIGTYPE_p_p_char msgv, int stackc, SWIGTYPE_p_p_char stackv) |
| HImUtility | public static void set_clip_rectangle(SWIGTYPE_p_ht_net_rendition nr, SWIGTYPE_p_ht_segment_info si) |
| HImUtility | public static void suppress_3d_geometry(SWIGTYPE_p_ht_net_rendition rendition, SWIGTYPE_p_ht_geometry geo3) |
| HImUtility | public static void draw_gradiated_window_background(SWIGTYPE_p_ht_net_rendition rendition, SWIGTYPE_p_ht_int_rectangle extent) |
| HImUtility | public static void draw_annotation_lines(SWIGTYPE_p_ht_net_rendition nr, SWIGTYPE_p_ht_polyline poly) |
| HImUtility | public static void draw_segment_in_background(SWIGTYPE_p_ht_net_rendition nr, SWIGTYPE_p_ht_dc_point points, SWIGTYPE_p_ht_rgba colors, SWIGTYPE_p_ht_plane planes, float[] hparams, int param_width, int param_flags) |
| HImUtility | public static void draw_dc_polyline_infront(SWIGTYPE_p_ht_net_rendition rendition, int count, SWIGTYPE_p_ht_dc_point geo3) |
| HImUtility | public static void draw_device_independent_line_weights(SWIGTYPE_p_ht_net_rendition rendition, int count, SWIGTYPE_p_ht_dc_point geo3) |
| HImUtility | public static void drawTextInfront(SWIGTYPE_p_ht_net_rendition rendition, SWIGTYPE_p_ht_text_info text_info) |
| HImUtility | public static void visible_hlr_polyline(SWIGTYPE_p_ht_net_rendition rendition, int count, SWIGTYPE_p_ht_dc_point geo3) |
| HIOConnector | public virtual bool GetHoopsEntities(IntPtr pKernelEntity, SWIGTYPE_p_vlist_s ret_HoopsKeysList) |
| HIOConnector | public virtual bool GetKernelEntities(MVO_POINTER_SIZED_INT key, SWIGTYPE_p_vlist_s ret_KernelEntitiesList) |
| HOpCameraWalk | public static int ImageAction(SWIGTYPE_p_HImageRegion ii, IntPtr data, SWIGTYPE_p_HButtonState keyup) |
| HOpCameraWalk | public void OnButtonWalk(string action, SWIGTYPE_p_HButtonState buttonstate) |
| HSelectionSet | public virtual SWIGTYPE_p_vlist_s GetSelectionList() |
| HSensorListener | public virtual int SensorActivatedEvent(SWIGTYPE_p_HBhvSensor sensor) |
| HUtility | public static void ShowContentsWithPath(string entitytypes, SWIGTYPE_p_p_vlist_s ret_pathlist, bool storePath, bool includeIncludes, bool filterIncludes) |
| HUtility | public static void ShowContentsWithPath(string entitytypes, SWIGTYPE_p_p_vlist_s ret_pathlist, bool storePath, bool includeIncludes) |
| HUtility | public static void ShowContentsWithPath(string entitytypes, SWIGTYPE_p_p_vlist_s ret_pathlist, bool storePath) |
| HUtility | public static void ShowContentsWithPath(string entitytypes, SWIGTYPE_p_p_vlist_s ret_pathlist) |
| HUtility | public static void MakeViewSnapshot(HBaseView view, int width, int height, SWIGTYPE_p_p_char data) |
Note that pointers to vlist and vhash are also not accessible via C# or Java.
MVO macros are not available in C#/Java. Function pointers are also not supported. Although methods with function pointers in their signatures can be seen by Intellisense, any calls to them will not compile. Member variables which are function pointers cannot be accessed either. Generally, if a parameter or variable has a data-type prefixed with SWIGTYPE, it is unlikely that it can be used in C# or Java. In the following example, the HIOManager's RegisterConnector method cannot be used in C#/Java because the parameters Create and Free are function pointers. In the C#/Java function declaration, it can be seen that Create and Free have datatypes prefixed with SWIGTYPE.
public virtual HIOConnector HIOManager::RegisterConnector(string file_type, SWIGTYPE_p_f_p_void__p_void Create, SWIGTYPE_p_f_p_void__void Free)
The following is a list of methods that cannot be accessed in C#/Java because they have functions pointers in their signature:
| HOOPS/MVO Class | HOOPS/MVO Method |
| HBaseView | public SWIGTYPE_p_f_p_q_const__char_unsigned_int_p_void__void GetEmitMessageFunction() |
| HBaseView | public SWIGTYPE_p_f_p_ht_net_rendition__void GetEventCheckerCallback() |
| HBaseView | public SWIGTYPE_p_f_unsigned_int_r_int__bool GetKeyStateCallback() |
| HBaseView | public void SetEmitMessageFunction(SWIGTYPE_p_f_p_q_const__char_unsigned_int_p_void__void new_emit_message_function) |
| HBaseView | public void SetEmitMessageFunction(SWIGTYPE_p_f_p_q_const__char_unsigned_int_p_void__void new_emit_message_function, IntPtr user_data) |
| HBaseView | public void SetEventCheckerCallback(SWIGTYPE_p_f_p_ht_net_rendition__void EventChecker) |
| HBaseView | public void SetKeyStateCallback(SWIGTYPE_p_f_unsigned_int_r_int__bool KeyState) |
| HBaseView | public uint SetSignalNotify(int signal, SWIGTYPE_p_f_int_p_void_p_void__bool callback, IntPtr user_data) |
| HIOManager | public HIOConnector RegisterConnector(string file_type, SWIGTYPE_p_f_p_void__p_void Create, SWIGTYPE_p_f_p_void__void Free) |
| HTClient | HTClient(float interval, HTCStyle style, SWIGTYPE_p_f_float_float_p_void__bool tick_function, IntPtr user_data) |
| HTClient | HTClient(float interval, HTCStyle style, SWIGTYPE_p_f_float_float_p_void__bool tick_function) |
| HTClient | public SWIGTYPE_p_f_float_float_p_void__bool GetTickFunction() |
| HTClient | public void SetTickFunction(SWIGTYPE_p_f_float_float_p_void__bool tick_function) |
Although some HOOPS/MVO classes are availabe in C#/Java, not all their methods can be used because of the design of either C# or Java. In these cases, HOOPS provides a variant especially designed for C#/Java users. Below is a list of classes, their inaccessible methods and their C#/Java variants.
| Class | Inaccessible Method | C#/Java Variant Method |
| HSelectionItem | virtual const HC_KEY * HSelectionItem::GetFullPathKeys (HBaseView *view) | virtual void HSelectionItem::GetFullPathKeys (HBaseView *view, System.Int32/System.Int64[] path) |
| HSmartSelItem | virtual const HC_KEY *const HSmartSelItem::GetIncludeKeys () const | virtual void HSmartSelItem::GetIncludeKeys (System.Int32/System.Int64[] includes) const |
| HSmartSelItem | virtual const HC_KEY * HSmartSelItem::GetFullPathKeys (HBaseView *view) | virtual void HSmartSelItem::GetFullPathKeys (HBaseView *view, System.Int32/System.Int64[] path) |
| HShellObject | int const * HShellObject::GetFlist () const | void HShellObject::GetFlist (int[] flist) const |
| HShellVertexData | float const *const HShellVertexData::GetFIndexData () const | void HShellVertexData::GetFIndexData (float[] data) const |
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 a C# sample program that integrates with HOOPS/Parasolid. It can be found in demo/csharp/csharp_simple_parasolid.