Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: COM
Hi there,
 
what is the best way to pass a user defined struct from an C# assembly to an unmanaged C++ .ocx via COM? Especially the dispatch_map(?) statement:
 
DISP_FUNCTION_ID(Foo, "Bar", dispidBar, Bar, VT_BOOL, VTS_UI1 VTS_UI1 VTS_UI1 VTS_UI1 [mycustomstruct])
 
Just got the project from someone who left without any useable documentation. Also i'm not familiar with com, dcom whatsoever. Any useful links would be appreciated. So far i found SafeArrays, VT_Record, ... but not really sure which one and how to use those. Same goes for dispatch maps ...
 
Thanks in advance,
crkn
Posted 27-Nov-12 6:36am
crkn113
Edited 27-Nov-12 6:37am
v2
Comments
Sergey Alexandrovich Kryukov at 27-Nov-12 12:49pm
   
Why COM? What's the roles of both components?
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

  Permalink  
Comments
ProgramFOX at 6-Dec-12 11:52am
   
Comment from the OP, posted as a non-answer (Solution 2):
Thanks for all that info Sergey.

Well, COM is needed because this is an (already released) device driver. The device is controlled, together with other devices, by a 3rd party software that uses COM for this purpose.

So it's something like this:

foobar.h
 

VARIANT_BOOL Connect(...);
VARIANT_BOOL Disconnect(void);
VARIANT_BOOL DoSomething(BYTE data1, BYTE data2, BYTE data3, BYTE data4);
VARIANT_BOOL DoSomethingToo(MyStruct* data);


foobar.cpp
 

BEGIN_DISPATCH_MAP(foobar, COleControl)
DISP_FUNCTION_ID(foobar, "DoSomething", dispid_DoSomething, DoSomething, VT_BOOL, VTS_UI1 VTS_UI1 VTS_UI1 VTS_UI1)
DISP_FUNCTION_ID(foobar, "DoSomethingToo", dispid_DoSomethingToo, DoSomethingToo, VT_BOOL, VTS_UI4)
END_DISPATCH_MAP()

VARIANT_BOOL foobar::DoSomethingToo(MyStruct* data)
{...}


foobar.idl
 

[uuid(...), ...]
library foobarLib
{
...
#include "Structs.h"
 
[uuid(...), ...]
dispinterface _foobarInterface
{
methods:
[id(3), helpstring("...")] VARIANT_BOOL DoSomethingToo(MyStruct* data);
}
}


Structs.h

 
[uuid(...)]
typedef struct
{
unsigned char b[4];
} MyStruct;


It's all about DoSomethingToo() which is an attempt to replace DoSomething(). The problem with this code is, when called from C#, that there's an unhandled COMException TYPE_E_ELEMENTNOTFOUND. So i'm guessing there's something wrong (or missing) with the struct declaration.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Thanks for all that info Sergey.
 
Well, COM is needed because this is an (already released) device driver. The device is controlled, together with other devices, by a 3rd party software that uses COM for this purpose.
 
So it's something like this:
 
foobar.h
VARIANT_BOOL Connect(...);
VARIANT_BOOL Disconnect(void);
VARIANT_BOOL DoSomething(BYTE data1, BYTE data2, BYTE data3, BYTE data4);
VARIANT_BOOL DoSomethingToo(MyStruct* data);
 
foobar.cpp
BEGIN_DISPATCH_MAP(foobar, COleControl)
    DISP_FUNCTION_ID(foobar, "DoSomething", dispid_DoSomething, DoSomething, VT_BOOL, VTS_UI1 VTS_UI1 VTS_UI1 VTS_UI1)
    DISP_FUNCTION_ID(foobar, "DoSomethingToo", dispid_DoSomethingToo, DoSomethingToo, VT_BOOL, VTS_UI4)
END_DISPATCH_MAP()
 
VARIANT_BOOL foobar::DoSomethingToo(MyStruct* data)
{...}
 
foobar.idl
[uuid(...), ...]
library foobarLib
{
    ...
    #include "Structs.h"

    [uuid(...), ...]
    dispinterface _foobarInterface
    {
        methods:
            [id(3), helpstring("...")] VARIANT_BOOL DoSomethingToo(MyStruct* data);
    }
}
 
Structs.h
[uuid(...)]
typedef struct
{
	 unsigned char b[4];
} MyStruct;
 
It's all about DoSomethingToo() which is an attempt to replace DoSomething(). The problem with this code is, when called from C#, that there's an unhandled COMException TYPE_E_ELEMENTNOTFOUND. So i'm guessing there's something wrong (or missing) with the struct declaration.
  Permalink  
Comments
ProgramFOX at 6-Dec-12 11:50am
   
If you've a comment to a answer, click on the "Have a Question or Comment?" button and you can write a comment. Don't post a comment as an answer.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

You just need to declare structure in MIDL (an idl file of your OCX object), make method in interface which you exporting and build your COM object so you will have type library inside your dll and you can just add your dll as reference in C# then the interop assembly will be generated automatically including the structures and whole marshaling stuff.
 
Regards,
Maxim.
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Sergey Alexandrovich Kryukov 881
1 OriginalGriff 270
2 Volynsky Alex 205
3 CPallini 180
4 Richard Deeming 175
0 OriginalGriff 5,640
1 Sergey Alexandrovich Kryukov 4,693
2 CPallini 4,540
3 George Jonsson 3,132
4 Gihan Liyanage 2,445


Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 6 Dec 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100