Solved

Receiving an array in a COM object

Posted on 2002-07-30
20
1,792 Views
Last Modified: 2013-11-25
I am using the ATL wizard to create a COM object. I want to pass a BYTE array to the COM object.

In the ATL Wizard I say that the Parameters are:
[in] long cItems, [in, size_is(cItems)] BYTE aItems[]

I have also tried:
[in] BYTE aItems[1000]

In both cases I get a compilation error:
warning MIDL2039 : interface does not conform to [oleautomation] attribute : [ Parameter 'aItems' of Procedure 'MyMethod' ( Interface 'IMyClass' ) ]

Can someone please give me some clues.
PS. I am a bit new to this stuff.
0
Comment
Question by:mikexxx
  • 9
  • 7
  • 2
  • +2
20 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 7188382
MIDL2039 : interface does not conform to [oleautomation] attribute
The interface does not meet the requirements for and Automation interface. Check to make sure the interface is derived from IUnknown or IDispatch.

Do you derive from one of these?
0
 
LVL 23

Expert Comment

by:Roshan Davis
ID: 7188470
Yuo can do 2 things

1. Chabge the BYTE[] to long and cast this long to BYTE pointer in your ATL control.

2. This may be the Direct way to do. Use OLESAFEARRAY to pass ARRAYs to ATL objects

Good Luck
0
 

Author Comment

by:mikexxx
ID: 7188886
Thanks for your suggestions.
I am wanting to pass binary data in a BYTE array from a VB application to a control written in C++. If I change the interface to long, the VB will not pass a byte array to it.

Your second option would work but is hard work. I cannot see from the documentation why my other methods would not work.
0
 
LVL 86

Expert Comment

by:jkr
ID: 7188896
To repeat my question - are you deriving your IF from IUnkown or IDispatch?
0
 
LVL 22

Expert Comment

by:ambience
ID: 7189610
i suppose for MIDL this has to be byte and not "BYTE", your BYTE is typedefed as unsigned char.

If you look closely it is just a warning and not an error, this seems to be quite un-explainable though as byte is a valid MIDL type and yet MIDL gives a warning, also try it with singned char and still it gives a warning.

Moreover the description of the error is mis-leading as it suggests that the interface may not be properly derived from IUnknown or IDispatch. Whereas the problem can only be that the interface takes types which may not be automation compatible.

But byte should be an automation compatible type, maybe you should ignore the warning and see if you really get any problems.
0
 

Author Comment

by:mikexxx
ID: 7190217
Sorry jkr, I didn't see your question. I was in rather a hurry earlier. I am deriving from IDispatch.

After a lot of experimentation and reading, I have got the following working:
[in] long cItems, [in, size_is(cItems)] BYTE *aItems

I am still interested why the other does not work though.

I have been looking in the following documents:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmsj99/html/wicked0599.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/midl/mi-laref_3zxv.asp

http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0898/idl/idl.htm&nav=/msj/0898/newnav.htm

0
 
LVL 22

Expert Comment

by:ambience
ID: 7190275
>> why the other does not work though.

Have you actually checked and found that the other methods dont work ?
0
 

Author Comment

by:mikexxx
ID: 7190932
What I meant was:

This works
[in] long cItems, [in, size_is(cItems)] BYTE *aItems

But this
[in] long cItems, [in, size_is(cItems)] BYTE aItems[]

and this
[in] BYTE aItems[1000]

do not work. They give a warning message at compilation as described above.

I have just tested all these 3 again.
0
 
LVL 22

Expert Comment

by:ambience
ID: 7192427
>> This works
[in] long cItems, [in, size_is(cItems)] BYTE *aItems
But this
[in] long cItems, [in, size_is(cItems)] BYTE aItems[]
and this
[in] BYTE aItems[1000]
do not work. They give a warning message at compilation as described above.

Sorry, maybe i did not make myself clear, i mean to ask that suppose you ignore the warning (the code compiles, right), so you test the compiled code from VB and see if it realy works or throws and error, or doesnot return anything at all ?

something like makking sure if the warning can be ignored or not.
0
 

Author Comment

by:mikexxx
ID: 7192807
When I use
[in] BYTE aItems[1000]
VB gives a compile error "Function or interface marked as restricted, or the function uses an Automation type not supported in Visual Basic".

When I use
[in] long cItems, [in, size_is(cItems)] BYTE aItems[]
VB gives a compile error "Type mismatch".


When I use
[in] long cItems, [in, size_is(cItems)] BYTE *aItems
In VB I have to pass an argument of aItems[0]. This seems to work though.
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 22

Expert Comment

by:ambience
ID: 7192821
how are you declaring the array in VB.
0
 

Author Comment

by:mikexxx
ID: 7192831
 Dim Buf(100) As Byte
  X = MyClass1.MyMethod(Buf(0))
0
 

Author Comment

by:mikexxx
ID: 7192842
I have just noticed that
[in] long cItems, [in, size_is(cItems)] BYTE aItems[]
forces me to make an assignment in the VB.
ie X = MyClass1.MyMethod(2, Buf(0))
rather than just
MyClass1.MyMethod(2, Buf(0))

[in] BYTE aItems[1000]
does not mind is I make an assignment or not.

I don't know what significance this has. It would suggest to me that VB is getting confused though.
0
 
LVL 22

Expert Comment

by:ambience
ID: 7192916
>> Dim Buf(100) As Byte

This in VB is declaration for a SafeArray of elements having type Byte.

say you have a method in VB like

Sub Method(arr() as Byte)
End Sub

Its equivalent in IDL would require

[id(0x1)] HRESULT Method([in, out] SAFEARRAY(unsigned char)* arr);
and not
[id(0x1)] HRESULT Method([in, out] byte arr[]);


I hope you see the difference, What you are passing from VB is an automation compatible safe-array of bytes (because arrays in VB are safe-arrays). But what your component expects is not a SafeArray. a Byte[] in IDL is not autmation type and is used by custom interfaces. It is because of this that you cannot use IDispatch::Invoke to pass a BYTE[].

It is because of the presence of a non-automation type that VB gives a type-mismatch.

This is also the reason MIDL complains about the interface having non-automation compatible types. Note that MIDL only complains if you are making a dispinterface not if you are making a custom interface.

You need to find a way in VB to pass something that can qualify as a byte[] and not a safearray. I suppose it might be possible using type-casts or something.If it is not possible then there is no other way but to change the interface definition and make it accept a type that is native to VB.

Hope this helps .. correct me if am wrong ..
0
 

Author Comment

by:mikexxx
ID: 7192961
I understand that VB thinks only in terms of SafeArrays.

Somehow in the example that works, COM is converting my data into a SafeArray and passing it to VB.

In the MSDN documents I refered to earlier, they suggest using the array type formats as an alternative to the pointers. They obviously thought it should work in some circumstances.

I don't think this is just a VB issue anyway. I get a warning message when compilling the C++.

Is it that the documents were talking about general COM rather than Active X? Is it that IDL supports arrays but Active X does not?

I think this maybe what you are saying?

The documents I was refering to are:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmsj99/html/wicked0599.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/midl/mi-laref_3zxv.asp

0
 
LVL 22

Expert Comment

by:ambience
ID: 7192996
here is an excerpt from the first article

"Returning variable-length data using indirect pointers is all fine and good for clients written in C++, but clients written in scripting languages such as VBScript require special handling. Today's scripting languages don't deal with C-style arrays very well; in fact, they don't deal with them at all. They expect arrays of data to be packaged in Automation-compatible SAFEARRAYs, which are great for script writers but a pain in the neck for programmers using C++."
0
 

Author Comment

by:mikexxx
ID: 7193191
I read that as being for just VBScript. In reality it probably means VB as well.

I have seen in other answers to questions on experts exchange that people seem to always say use SafeArrays. The method I found that appeared to work is much simpler.

Is there anything wrong with doing it that way?
0
 
LVL 22

Accepted Solution

by:
ambience earned 300 total points
ID: 7193249
No there is nothing wrong with it as long as the array is of Numeric type, this is because numeric array elements are always laid out consecutively in memory.

Note that you are passing reference (address) of first element of Buf and not the reference to Buf and that is why this will work.

MyMethod(Buf(0)) will work.
MyMethod(Buf)  should not work.

0
 

Author Comment

by:mikexxx
ID: 7193295
Thanks for all your help. I have learnt a lot from you.
0
 

Expert Comment

by:Banjo-ExVB
ID: 9032611
Although the use of SAFEARRAYS is all well and good, the cause of the original error is much simpler.  BYTE is a C type and is not recognised by COM as valid for OLE Automation.  The COM type that equates to Byte in VB is unsigned char.  So:

[in] unsigned char aItems[1000]

Should show up in VB as:

aItems(0 to 999) As Byte
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

758 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now