Having hard time marshalling parameters from C++ to .Net?

Having hard time marshalling parameters from C++ to .Net?

  • Comments 1

If you are finding it difficult to send parameters from C++ to .Net, try if you can use the following class:

--------------------------------------------------------------------------------------------------------------------------------

#ifndef __PARAMETERS_H_A1B7ECCA_1691_43d0_ACDD_EBE1208005F9
#define __PARAMETERS_H_A1B7ECCA_1691_43d0_ACDD_EBE1208005F9

#include <Comdef.h>

#ifdef _DEBUG
 #define NO_ERROR_CHECKING FALSE //Use Error Checking for Debug Versions (throws Exception from Constructor !!)
#else
 #define NO_ERROR_CHECKING TRUE //Turn-off Error Checking for Release Versions
#endif

#ifndef _MFC_VER //Check if this is NON-MFC application
 typedef const SAFEARRAY* LPCSAFEARRAY;
#endif

class CParameters
{
  int m_nParamCount;
  int m_nCurParam;
  SAFEARRAY* m_pSA;

 inline bool IsInvalid()
 {
   return m_nCurParam >= m_nParamCount || m_pSA == NULL;
 }
public:

 CParameters(int nCount)
 {
   m_nCurParam = 0;
   m_nParamCount = nCount;

   SAFEARRAYBOUND bounds[] = {{nCount,0}}; //Array Contains 'nCount' Elements starting from Index '0'
   m_pSA = SafeArrayCreate(VT_VARIANT,1,bounds); //Create a one-dimensional SafeArray of variants 

   #if NO_ERROR_CHECKING == FALSE
     if(m_pSA == NULL) throw "Exception: Unable to Create Safe Array";
   #endif
 }

 ~CParameters(void)
 {
   if(m_pSA)
   {
     SafeArrayDestroy(m_pSA);
     m_pSA = NULL;
   }
 }

 inline operator LPSAFEARRAY() const { return m_pSA; }
 inline operator LPCSAFEARRAY() const { return m_pSA; }
 inline int GetCount() const { return m_nParamCount; }

 inline HRESULT AddParameter(const bool& bParamVal)
 {
   #if NO_ERROR_CHECKING == FALSE
   if(IsInvalid()) return E_FAIL;
   #endif

   long lIndex[] = { m_nCurParam++ };
   VARIANT var;
   var.vt = VT_BOOL;
   var.boolVal = bParamVal;
   return SafeArrayPutElement(m_pSA, lIndex, &var);
 }

 inline HRESULT AddParameter(const long& lParamVal)
 {
   #if NO_ERROR_CHECKING == FALSE
    if(IsInvalid()) return E_FAIL;
   #endif

    long
lIndex[] = { m_nCurParam++ };
    VARIANT var;
    var.vt = VT_I4;
    var.lVal= lParamVal;
    return SafeArrayPutElement(m_pSA, lIndex, &var);
 }

 inline HRESULT AddParameter(LPCTSTR lpszParamVal)
 {
  try
  {
    #if NO_ERROR_CHECKING == FALSE
     if(IsInvalid()) return E_FAIL;
    #endif

    long lIndex[] = { m_nCurParam++ };
    VARIANT var;
    var.vt = VT_BSTR;
    var.bstrVal = SysAllocString(bstr_t(lpszParamVal));
    return SafeArrayPutElement(m_pSA, lIndex, &var);
  }
  catch(_com_error& e)
  {
    return e.Error();
  }
 }

 inline HRESULT AddParameter(const LPCTSTR lpszArray[], int nCount)
 {
  try
  {
    #if NO_ERROR_CHECKING == FALSE
     if(IsInvalid()) return E_FAIL;
    #endif

    VARIANT var;
    SAFEARRAYBOUND bounds[] = {{nCount,0}}; //Array Contains 'nCount' Elements starting from Index '0' 

    var.vt = VT_ARRAY | VT_BSTR;
    var.parray = SafeArrayCreate(VT_BSTR,1,bounds); //Create a one-dimensional SafeArray of variants

    if(var.parray == NULL)
      return E_OUTOFMEMORY;

    for(long i=0; i < nCount; ++i)
    { 
      HRESULT hr = SafeArrayPutElement(var.parray, &i, SysAllocString(bstr_t(lpszArray[i])));
      if(FAILED(hr)) return hr;
    }

    long lIndex[] = { m_nCurParam++ };
    return SafeArrayPutElement(m_pSA, lIndex, &var);
  }
  catch(_com_error& e)
  {
    return e.Error();
  }
 }
};

#endif //__PARAMETERS_H_A1B7ECCA_1691_43d0_ACDD_EBE1208005F9

--------------------------------------------------------------------------------------------------------------------------------

Using this class is simple and straight forward. Declare a CParameters variable and call CParameters::AddParameter() once for each argument you want to send to .Net.

For example, to invoke a method in .net that has prototype

   void Foo(string strName, int nLen);
use the following from C++:

  CParameters param(2);        // Two parameters for the method 

  param.AddParameter("Hello World!!"); // strName

  param.AddParameter(13);       // nLen  = strlen(strName)

  spFoo->Invoke_3(..., param); // Invoke the Foo function with the Arguments

You are welcome to add support for CParameters class to accept more types. For similar handy classes, visit http://www.geocities.com/krishnapg/

Attachment: Parameters.h
Leave a Comment
  • Please add 5 and 1 and type the answer here:
  • Post