Click here to Skip to main content
15,892,809 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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
Updated 27-Nov-12 6:37am
v2
Comments
Sergey Alexandrovich Kryukov 27-Nov-12 12:49pm    
Why COM? What's the roles of both components?
--SA

 
Share this answer
 
Comments
Thomas Daniels 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.
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
C++
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
C++
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
C++
[uuid(...), ...]
library foobarLib
{
    ...
    #include "Structs.h"

    [uuid(...), ...]
    dispinterface _foobarInterface
    {
        methods:
            [id(3), helpstring("...")] VARIANT_BOOL DoSomethingToo(MyStruct* data);
    }
}


Structs.h
C++
[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.
 
Share this answer
 
Comments
Thomas Daniels 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.
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.
 
Share this answer
 

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900