How to use IDispatch in plain C to call a COM object
Asked Answered
B

3

17

I need to compile some code of mine using the gcc compiler included in the R tools (R the statistical program for windows), the problem is that I need to use IDispatch in my code to create an access the methods of a COM object, and the gcc compiler doesn't support much of the code that I'm using to do so, which is basically C++ code.

So my question is how can I use IDispatch in C to create the COM object without having to depend on MFC, .NET, C#, WTL, or ATL. I believe that if I do so I will be able to compile my code without any problem.

Babylonia answered 3/6, 2009 at 17:42 Comment(0)
U
20

There is a great article on CodeProject entitled "COM in plain C".

Here is the link to Part 1.

There is a lot of very good info on working with COM in C in that article and the author's subsequent follow-ups (I think there are 3 or 4 in the series).

Edit:
I was wrong, there are 8 parts!

Part 2
Part 3
Part 4
Part 5
Part 6
Part 7
Part 8

Unmeriting answered 3/6, 2009 at 18:11 Comment(2)
this is a very good tutorial indeed, I was looking at it, and the first part explains how to create a COM object, which I already have, the problem is that my COM object is written in C#, I saw in the tutorial that you need to create a include(.h) file in which you must specify the VTable's, GUIDs and structures in your COM object, now, can I do this even if my COM object is C#?Babylonia
Hmm - I would imagine it is possible, do you register your C# COM object in the Registry? I think that's all that is necessary. COM is a binary standard, so the VTable should be the same regardless of whether it's implemented in C#, C++, VB, etc.Unmeriting
C
5

In general, a C++ IDispatch interface is just a table of function pointers. In C, it would look something like:

typedef struct {
  HRESULT(*pQueryInterface)(void* this, REFIID riid, void **ppvObject);
  ULONG(*pAddRef)(void* this);
  ULONG(*pRelease)(void* this);
  HRESULT(*pGetTypeInfoCount)(void* this, unsigned int* pctInfo);
  HRESULT(*pGetTypeInfo)(void* this, unsigned int iTInfo,LCID lcid, ITypeInfo** ppTInfo);
  HRESULT(*pGetIDsOfNames)(void* this, REFIID riid, OLECHAR** rgszNames, unsigned int cNames, LCID lcid, DISPID* rgDispId);
 HRESULT(*pInvoke)(void* this, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, unsigned int* puArgErr);
} IDispatch_in_C;

Note that every method has a THIS pointer as the first parameter, and that you will need to define more types, such as ITypeInfo, REFIID, DISPID, etc, etc.

So, its a big task. But it is possible to create C++ interfaces in pure C.

Ciaphus answered 3/6, 2009 at 18:11 Comment(2)
Note that you need to make sure your calling conventions match up otherwise your parameter passing order and stack cleanup will not work properly. Be sure that these methods are declared as using the 'stdcall' calling convention.Gurley
this doesn't quite explain the fact that IDispatch in C++ uses thiscall, so it passes this via ecx and not on the stack; whereas in C it passes this via stack and not ecx; whereas CoCreateInstance doesn't care if you're using C or C++. Makes no sense why one of the versions doesn't fail due to wrong calling convention. Also as stated above, your example defaults to cdecl whereas com expects stdcall, so you end up cleaning the stack twice effectively corrupting it.Francophobe
C
4

Also you can use disphelper library.

Confluence answered 4/6, 2009 at 11:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.