?
Solved

How do you pass an array to a COM object using interop?

Posted on 2006-05-24
5
Medium Priority
?
836 Views
Last Modified: 2008-01-09
I need to extend an existing COM object to add a function that takes as input an array of bytes, which is readonly. I haven't done COM in a while and I don't remember the gory details so hopefully someone here can help me fill in the blanks.

The interface definition looks something like this:

[object, dual, uuid("12345678-1234-1234-1234-123456789ABC") ]
__interface IMyFoo {
  [id(1), helpstring("method foo1")] HRESULT foo1([in] BSTR str, [out,retval] BSTR* result);
  [id(2), helpstring("method foo2")] HRESULT foo2([in] BYTE buf[], [in] LONG numBytes, [out,retval] BSTR* result);  // <-- #1 below
};

[ coclass, uuid("87654321-4321-4321-4321-CBA987654321"), default(IMyFoo) ]
class CMyFoo : public IMyFoo
{
public:
  CMyFoo(void);
  ~CMyFoo void);
  STDMETHOD(foo1)(BSTR str, LONG* result);
  STDMETHOD(foo2)(BYTE []buf, LONG numBytes, BSTR* result);  // <--#1 below
};

The implementation of foo2 is conceptually something like:

STDMETHODIMP CMyFoo::foo2(BYTE []buf, LONG numBytes, BSTR* result)
{

  int sum = 0;
  for (int i=0; i<numBytes; i++) {
     // process buf here
     sum +=  buf[i]; // <--- #2 below
  }
 
  char outstr[50];
  sprintf(outstr, "answer is %ld", sum);

  *result = ::SysAllocString((OLECHAR *) outstr);

  return S_OK;
}

From the C# side, I want to do something like:

byte[] buf = new byte[1234];
// buf gets data in it, not important how

mycom.CMyFooClass myfoo = new mycomCMyFooClass();
string sum= myfoo.foo2(buf, buf.length);  // <--- #3 below

I've already got everything working to call the foo1() function in C#, but I need help with

#1) setting up the interface to be able to pass an array of bytes in foo2()
#2) accessing that array within the COM object function foo2() - don't need to modify it, just access it
#3) how do I call foo2() from the C# side to pass the array

Thanks!
0
Comment
Question by:wayside
  • 2
  • 2
4 Comments
 
LVL 12

Accepted Solution

by:
gbzhhu earned 1500 total points
ID: 16754270
0
 
LVL 14

Author Comment

by:wayside
ID: 16755208
gbzhhu,

That article isn't very helpful.

This article is much more helpful, it shows actual sample code:

http://www.codeguru.com/Cpp/COM-Tech/activex/misc/article.php/c2577/

So I set up my code like this, and it works great. If you see any issues please let me know.


[object, dual, uuid("12345678-1234-1234-1234-123456789ABC") ]
__interface IMyFoo {
  [id(1), helpstring("method foo1")] HRESULT foo1([in] BSTR str, [out,retval] BSTR* result);
  [id(2), helpstring("method foo2")] HRESULT foo2([in] VARIANT buf, [in] LONG numBytes, [out,retval] BSTR* result);
};

[ coclass, uuid("87654321-4321-4321-4321-CBA987654321"), default(IMyFoo) ]
class CMyFoo : public IMyFoo
{
public:
  CMyFoo(void);
  ~CMyFoo void);
  STDMETHOD(foo1)(BSTR str, LONG* result);
  STDMETHOD(foo2)(VARIANT buf, LONG numBytes, BSTR* result);
};

STDMETHODIMP CMyFoo::foo2(VARIANT buf, LONG numBytes, BSTR* result)
{
  void *pData;
  if (buf.vt == (VT_ARRAY | VT_UI1)) {
    SafeArrayAccessData(buf.parray, &pData); // Get the data
    SafeArrayUnaccessData(buf.parray);           // Unaccess it.
  }
  else
    return S_FALSE;

  unsigned char pUChar = (unsigned char *)pData;
  int sum = 0;
  for (int i=0; i<numBytes; i++) {
     // process buf here
     sum +=  pUChar [i];
  }
 
  char outstr[50];
  sprintf(outstr, "answer is %ld", sum);

  *result = ::SysAllocString((OLECHAR *) outstr);

  return S_OK;
}

From the C# side:

byte[] buf = new byte[1234];
// buf gets data in it, not important how

mycom.CMyFooClass myfoo = new mycomCMyFooClass();
string sum= myfoo.foo2(buf, buf.Length);

0
 
LVL 12

Expert Comment

by:gbzhhu
ID: 16759310
I am glad it is working for you.  The article I pointed out suggested using safesarrays and variants rather than byte array.  The other article does the same but gave example code which I agree is better
0
 
LVL 14

Author Comment

by:wayside
ID: 16950921
Sorry, I should have closed this before.
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Najam
Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
The Relationships Diagram is a good way to get an overall view of what a database is keeping track of. It is also where relationships are defined. A relationship specifies how two tables connect to each other. As you build tables in Microsoft Ac…
Stellar Phoenix SQL Database Repair software easily fixes the suspect mode issue of SQL Server database. It is a simple process to bring the database from suspect mode to normal mode. Check out the video and fix the SQL database suspect mode problem.
Suggested Courses

621 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question