2009-06-03 8 views
12

Necesito compilar algún código mío usando el compilador gcc incluido en las herramientas R (R el programa estadístico para Windows), el problema es que necesito usar IDispatch en mi código para crear un acceso a los métodos de un objeto COM, y el compilador gcc no admite gran parte del código que estoy usando para hacerlo, que básicamente es código C++.Cómo usar IDispatch en C simple para llamar a un objeto COM

Así que mi pregunta es cómo puedo usar IDispatch en C para crear el objeto COM sin tener que depender de MFC, .NET, C#, WTL o ATL. Creo que si lo hago, podré compilar mi código sin ningún problema.

Respuesta

15

Hay un gran artículo sobre CodeProject titulado "COM in plain C".

Aquí está the link to Part 1.

Hay mucha información muy buena sobre cómo trabajar con COM en C en ese artículo y los seguimientos posteriores del autor (creo que hay 3 o 4 en la serie).

Editar:
que estaba equivocado, hay 8 partes!

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

+0

este es un muy buen tutorial de hecho, lo estaba viendo, y la primera parte explica cómo crear un objeto COM, que ya tengo, el problema es que mi objeto COM está escrito en C#, vi en el tutorial que necesita crear un archivo de inclusión (.h) en el que debe especificar las VTable, los GUID y las estructuras en su objeto COM, ahora, ¿puedo hacer esto incluso si mi objeto COM es C#? – Vic

+0

Hmm - Me imagino que es posible, ¿registras tu objeto COM C# en el Registro? Creo que eso es todo lo que es necesario. COM es un estándar binario, por lo que la tabla debe ser la misma independientemente de si está implementada en C#, C++, VB, etc. –

3

En general, una interfaz IDispatch de C++ es solo una tabla de punteros a funciones. En C, se vería algo como:

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; 

Tenga en cuenta que cada método tiene un este puntero como primer parámetro, y que tendrá que definir más tipos, tales como ITypeInfo, REFIID, DISPID, etc, etc.

Por lo tanto, es una gran tarea. Pero es posible crear interfaces C++ en C. puro

+2

Tenga en cuenta que debe asegurarse de que sus convenciones de llamadas coincidan, de lo contrario su orden de paso de parámetros y la limpieza de la pila no funcionarán correctamente. Asegúrese de que estos métodos estén declarados como usando la convención de llamadas 'stdcall'. –

+0

esto no explica el hecho de que IDispatch en C++ usa thiscall, por lo que pasa esto a través de ecx y no en la pila; mientras que en C pasa esto a través de stack y no de ecx; mientras que a CoCreateInstance no le importa si estás usando C o C++. No tiene sentido por qué una de las versiones no falla debido a una convención de llamadas incorrecta. También como se indicó anteriormente, su ejemplo está predeterminado en cdecl mientras que com espera stdcall, por lo que termina limpiando la pila dos veces y lo corrompe. – Dmitry

Cuestiones relacionadas