468,532 Members | 1,629 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,532 developers. It's quick & easy.

Using an STL vector in a struct with COM

I need to pass an STL Vector to a Visual Basic program using COM. This has to be a vector of a user defined structure and it has to also be within a structure itself.

As near as I can tell, I have all of the pieces working. I can create a structure within a structure that COM can use. Using a generic type, I can create a vector that COM can pass to VB. Using a structure that COM can pass to VB, I can create a vector, but I can't get COM to pass that structure to VB.

I am following this MSDN article on how to pass STL containers through COM.

http://msdn2.microsoft.com/en-us/library/3stwxh95(VS.80).aspx

The article is pretty good, but it is just passing strings and doesn't talk at all about UDT's.

Some more specifics... I am trying to implement the get_Item method which should, given an index, return the object stored in the vector at the index. I don't know if the 'return' variable type should be a CComVariant, an IUnknown, one of my structs or what... It would make sense for it to be one of my structs, but it appears that for VB to recognize it, it has to be one of the other two mentioned. I don't know if this would work with ANY struct that VB can see through the COM interface.

If anyone can help me, I would be grateful.

- Matt
Aug 1 '07 #1
11 2863
weaknessforcats
9,207 Expert Mod 8TB
You are implementing IDispatch, yes?? Those are the methods that VB can see.

So, your vector of your structs is inside your COM object and you interface to Visual Bascis using [url=http://msdn2.microsoft.com/en-us/library/x295h94e(VS.80).aspx]_variant_t]/url].

This is a wrapper of VARIANT.

The translation between VARIANT and your user-defined struct should be done inside the COM object.
Aug 1 '07 #2
You are implementing IDispatch, yes?? Those are the methods that VB can see.

So, your vector of your structs is inside your COM object and you interface to Visual Bascis using [url=http://msdn2.microsoft.com/en-us/library/x295h94e(VS.80).aspx]_variant_t]/url].

This is a wrapper of VARIANT.

The translation between VARIANT and your user-defined struct should be done inside the COM object.
Right... This is my immediate problem. I'm not sure how to convert or typecast my datatype to a VARIANT. I thought a VARIANTwas only a union of a bunch of different data types. I'm pretty sure mine isn't one of them.

I can access the STL Vector through VB, but just simple stuff like the number of elements in the vector. I'm falling on my face when it comes to getting an actual member of the vector. The error I get states that (in short) there isn't a known conversion with a right hand side of my structure.

Thank you for the help.
Aug 2 '07 #3
weaknessforcats
9,207 Expert Mod 8TB
If you are using IDispatch, then Visual Basic will call Invoke which will call your IDispatch::Invoke().

You will need:
Invoke.
GetIdsOfNames.
DISPPARAMS.
VARIANT.

Read the automation docs carefully.
Aug 2 '07 #4
If you are using IDispatch, then Visual Basic will call Invoke which will call your IDispatch::Invoke().

You will need:
Invoke.
GetIdsOfNames.
DISPPARAMS.
VARIANT.

Read the automation docs carefully.
I have a question for you before I dive into the URL's you gave me... Do you see the answer and are trying to lead me towards it or do you not know exactly what I'm talking about but think that I could maybe possibly scratch out an answer from the above URL's? I'm not being nasty, just curious whether or not you could give me the answer if you wanted to. (Meaning that you would be able to direct my path past the above advice if necessary.)
Aug 2 '07 #5
I have a question for you before I dive into the URL's you gave me... Do you see the answer and are trying to lead me towards it or do you not know exactly what I'm talking about but think that I could maybe possibly scratch out an answer from the above URL's? I'm not being nasty, just curious whether or not you could give me the answer if you wanted to. (Meaning that you would be able to direct my path past the above advice if necessary.)
In reading the material, I had another idea I wanted to run by you... Would it be a simpler solution (though maybe not as elegant) to pass an array back and forth and dynamically create the vector when the array is passed from the VB routines to the COM DLL? It should be a one way street from VB to our API for this particular object... And I think that passing an array is much easier to do than this whole STL Vector mess. So does that sound like a good approach or am I just wussing out?
Aug 2 '07 #6
weaknessforcats
9,207 Expert Mod 8TB
The key here is that you have to implement IDispatch in your COM object.

That you use an STL container is irrelevant.

Your implementations of IDispatch::GetTypeInfoCount, IDispoatchGetTypeInfo, IDispatchGetIDsOfNames and IDispatch::Invoke is how to interact with VB. It will be your functions that are called by your VB client.

Implementing IDispatch will allow your COM object to appear in the VB Object Browser.

You will also need to implement IUnknown.

Try to use a multi-threaded apartment to avoid marshaling. Marshaling is so incrdibly slow. However, your COM object must be multithreaded. That means no global or static variables of any kind and common accesses protected by locks.

Read everything about OLE automation. I assume you have books on COM.

I really do not want to write your code.
Aug 3 '07 #7
The key here is that you have to implement IDispatch in your COM object.
I am.

That you use an STL container is irrelevant.
Can't be irrelevant since this is where I'm having the problem.

Your implementations of IDispatch::GetTypeInfoCount, IDispoatchGetTypeInfo, IDispatchGetIDsOfNames and IDispatch::Invoke is how to interact with VB. It will be your functions that are called by your VB client.
Have lots of functions available to VB. The one to return an object from the vector is the one that isn't working.

Implementing IDispatch will allow your COM object to appear in the VB Object Browser.
COM object does appear in the VB Object browser. I'm pretty sure that I mentioned in my first or second post that I was able to interact with the vector, just not return one of the vector elements to VB. (Or add one to the vector, for that matter...)

You will also need to implement IUnknown.
Why? What does this mean? Where does it fit in?

Try to use a multi-threaded apartment to avoid marshaling. Marshaling is so incrdibly slow. However, your COM object must be multithreaded. That means no global or static variables of any kind and common accesses protected by locks.
It is multithreaded, no global or static variables in sight. I haven't yet bothered with the locks.

Read everything about OLE automation. I assume you have books on COM.
I have a few old ones. As yet, not very useful to me. I will look up OLE automation. Maybe now I know enough to be able to make sense of what is said.

I really do not want to write your code.
It's a darn good thing that I have never asked you to write code for me then, isn't it. If you saw my code, you would be grateful that you weren't the one to write it.

All I'm trying to do is understand what is going on so that I can do something useful. New job. This is my first project. With the help of this forum I've overcome most of the obstacles to finishing. I *think* that this is the last one. At least, it's the last identified one. I think our goals are the same. I am NOT asking for a solution, just guidance. I don't want to come out of this experience with the equivalent of this discussion.

Me: How do you put "Hello World" on the screen?
You: cout << "Hello World" << endl;
Me: Great! Now how do I put "Hello Cruel World" on the screen?
You: It's the same as the first question.
Me: I tried that. It just prints Hello World.

Anyway... I'm rambling. I am grateful for the help.
Aug 3 '07 #8
I should have asked, are there any really good COM/COM+/ATL books you would recommend that cover the versions of the above that correspond to VS 2005?

In case you were curious... Passing a safe array seems to work fine. It's kinda ugly, in my opinion, but I don't know how to make it better. I'm declaring a structure in my idl file, putting a 'struct myDataType;' in the library section of the idl file, creating an instance of that struct in VB and then I have to create an array in VB and assign it to the array in the struct for it to work. It does work, but I have to think that there is a better way.
Aug 3 '07 #9
weaknessforcats
9,207 Expert Mod 8TB
Passing a safe array seems to work fine. It's kinda ugly, in my opinion,
This is what I have been trying to coimmunicate. VB uses VARIANT. A SAFEARRAY is a known VARIANT member.

Your VB code has to discover the method arguments and the types of those arguiments. On the C++ side you do not send a vector element to VB unless it can be a member of a VARIANT.

For a complex struct in the vector, you will need to disassemble it into its component parts and pass them as VARIANT members.

VB should:
1) call GetIDsOfNames to get the DISPID of a property
2) use the DISPIDs in calls to Invoke.

This is pretty well covered in MSDN.
Aug 4 '07 #10
I hope you will indulge one last question on this thread. It's probably a bonehead question, but google was not my friend today.

I have the array passing back and forth just fine. One problem I am having, however, is that on the VB side of the world, I have to create an array manually and assign it to the array in the data structure. Does this sound right to you?

It would appear from the behavior that I am seeing that when I create the object from my COM interface, memory isn't set aside for the array. I don't know how to have or mimic a 'constructor' and my array methods and parameters are somewhat limited.

I know memory has to be set aside at some point, I'm just not sure at which point in this case..

I think the next question would be about mimicking the behavior of a vector (more or less unlimited size) instead of having a fixed size. Does such a thing exist in VB? (If not, I'm going to set an arbitrary 1024 object limit for my array. Bad Programmer! BAD BAD Programmer!)

If you want to see code, let me know.
Aug 6 '07 #11
weaknessforcats
9,207 Expert Mod 8TB
I am not an expert here but I believe only a SAFEARRAY is going to work.

My gut feeling is to keep the vector in the COM object and just let VB interact with it though the COM interfaces.

Otherwise, creating the array on the VB side and assigning sound correct. It seems doing it this way make the COM object kinda pointless. However, I have no real knowledge of what you are doing.

My first measure is: Does is work? If yes, then any changes are just improvements. But software that doesn't work is useless regardless of how slick the code is.
Aug 7 '07 #12

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

9 posts views Thread by J. Campbell | last post: by
4 posts views Thread by Peter Mrosek | last post: by
6 posts views Thread by justyb11 | last post: by
reply views Thread by Sudheer Gupta | last post: by
3 posts views Thread by Sudheer Gupta | last post: by
3 posts views Thread by capes | last post: by
10 posts views Thread by The Cool Giraffe | last post: by
1 post views Thread by fmendoza | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.