Share via


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

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 https://www.geocities.com/krishnapg/

Parameters.h

Comments