6

I am a COM object written in ATL that is used from a C++ application, and I want to pass an array of BYTEs between the two. My experience of COM/IDL so far is limited to passing simple types (BSTRs, LONGs, etc.).

Is there a relatively easy way to have the COM object pass an array to the caller? For example, I want to pass a raw image (TIFF) instead of messing with temporary files.

1
  • 13
    How fun it must be to be a COM object. :-) Commented Feb 23, 2010 at 5:07

4 Answers 4

11

Try passing a safearray variant to the COM Object. Something like this to put a BYTE array inside a safearray variant....

bool ArrayToVariant(CArray<BYTE, BYTE>& array, VARIANT& vtResult)
{
SAFEARRAY FAR*  psarray;
SAFEARRAYBOUND sabounds[1]; 

sabounds[0].lLbound=0;
sabounds[0].cElements = (ULONG)array.GetSize();

long nLbound;

psarray = SafeArrayCreate(VT_UI1, 1, sabounds);
if(psarray == NULL)
    return false;

for(nLbound = 0; nLbound < (long)sabounds[0].cElements ; nLbound++){
    if(FAILED(SafeArrayPutElement(psarray, &nLbound, &array[nLbound]))){
        SafeArrayDestroy(psarray);
        return false;
    }
}

VariantFree(vtResult);
vtResult.vt = VT_ARRAY|VT_UI1;
vtResult.parray = psarray;
return true;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks - I found a very useful ATL class called CComSafeArray that makes this very easy (older versions of MFC can use COleSafeArray).
2

SAFEARRAYs are the way to go if you want OLE-Automation compliance, and maybe use the COM interface from other languages such as VB6. But there is an alternative in IDL, for example: -

void Fx([in] long cItems, [in, size_is(cItems)] BYTE aItems[]);

This describes a method where the marshalling code can infer the number of bytes to be transfered by inspecting the value of the first parameter.

This is fine if your clients are all written in C/C++, but i think that an interface containing this would not be automation-compliant, so not usable from VB6, and possibly the standard marshaler will not be able to do the marshaling, so you'd need to generate your own proxy/stub DLL from the IDL. Not hard to do, but a bit harder than using SAFEARRAYs.

Comments

0

Check out using safearrays. Here's some example code:

The safearray is returned as a pointer to a VARIANT

[id(1), helpstring("LogCache")] HRESULT LogCache([out,retval] VARIANT* logCache);

Safearrays are pretty easy to use. Here's some example code which is a cache of the latest 1000 log messages of some application:

   safearray_t<bstr_t> m_logCache;
   ...
   if (m_logCache.size() > 1000)
   {
       m_logCache.pop_back();
   }

   m_logCache.push_front(Msg.str(), 0);


    variant_t LogCache()
    {
        if (!m_logCache.is_empty())
        {
            variant_t cache(m_logCache);
            return cache;
        }
    }

Note that the syntax in your case is almost certainly going to be different since I'm using the comet COM library, but the ideas/concepts are the same.

Comments

-2

You can use BSTR to pass an array of bytes.

BYTE array[buffer_size];
...
BSTR toBePassed = SysAllocStringByteLen((OLECHAR*)array,length);
YourCOMMethod(toBePassed);
SysFreeString(toBePassed);

In your method:

BYTE* pData = (BYTE*)bstrPassed;
DWORD dataLength = SysStringByteLen(bstrPassed);

3 Comments

DON'T DO IT. The array contents might get translated from their ANSI code page to Unicode or vice versa, causing the binary values to change. Client applications might not always know when this happens, and they will find their data corrupted.
To clarify: Even though the programmer intends the array to hold binary data, various system routines don't know the programmer's intention. BSTRs are designed to hold Unicode strings, and system routines will make that assumption.
OLECHAR is a wide char i.e. 16bits, a byte/normal char is 8bits. this will not work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.