studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones visual-c++ com atl

visual c++ - programacion - Cómo se puede usar COM para transferir datos entre dos procesos



manual de programacion android pdf (2)

COM es un gran tema y no es posible explicarlo en formato de respuesta de desbordamiento. Lo que intentaré hacer es demostrar el ejemplo más simple de servidor COM fuera de proceso local y cliente COM (lo más breve posible) con la ayuda de los asistentes ATL de Visual Studio (siempre que mencione ATL en las etiquetas) que generarán la mayor parte del código y esto le da la posibilidad de probar el enfoque COM e investigar fuentes repetitivas. Pero para una mejor comprensión recomiendo encontrar la implementación inproc del servidor COM sin ATL, solo con C ++.

  1. Crear proveedor de estructura:

    • Cree un nuevo proyecto ATL con el nombre COMStructProvider (seleccione la plantilla de proyecto ATL en Visual C ++). En el asistente, seleccione el tipo de aplicación "Ejecutable" (no DLL). Otra opción por defecto. Wizard generará archivos de proyecto.
    • Seleccione Proyecto -> Agregar clase -> Objeto simple ATL -> Agregar. En nombre corto, escriba el nombre arbitrario, por ejemplo MyStruct. Haga clic en "Finalizar". Esto agregará el encabezado y el archivo de implementación para MyStruct coclass. También se agregarán MyStruct.rgs para ayudar a registrar su coclass en el registro. Ahora tiene un servidor COM mínimo y puede construir una solución, pero para hacerlo necesita ejecutar VS como administrador (porque registrará su servidor en el registro), de lo contrario, el registro fallará.
    • Agregue dos miembros de datos a CMyStruct (VS antependen clase con C de manera predeterminada) class: private: std :: string m_name; int m_age;
    • Durante los pasos anteriores, el asistente creó la interfaz IMyStruct (puede verla en el archivo idl). Ahora queremos agregar métodos a esta interfaz: getters y setters a nuestros dos miembros de datos privados. Seleccione la pestaña Vista de clase, seleccione la interfaz IMyStruct (derivada de IDispatch), seleccione en el menú contextual "agregar método". Por ejemplo, el nombre del método getAge con el parámetro LONG *, los atributos del parámetro "out" y el nombre del parámetro: age (haga clic en Agregar para agregar el parámetro). Esto agrega un nuevo método al archivo idl y al archivo header e impl. Repita la adición de métodos para setAge (en el parámetro de tipo LONG), getName (out, BSTR *), setName (in, BSTR). El nombre de los parámetros no importa.

En el archivo idl, tendrá algo así: proporciono esto como punto de control de que todos los pasos se realizan correctamente:

import "oaidl.idl"; import "ocidl.idl"; [ object, uuid(AA2DA48C-CD1E-4479-83D4-4E61A5F188CB), dual, nonextensible, pointer_default(unique) ] interface IMyStruct : IDispatch{ [id(1)] HRESULT getAge([out] LONG* age); [id(2)] HRESULT setAge([in] LONG age); [id(3)] HRESULT getName([out] BSTR* name); [id(4)] HRESULT setName([in] BSTR name); }; [ uuid(E7A47886-D580-4853-80AE-F10FC69E8D73), version(1.0), ] library COMStructProviderLib { importlib("stdole2.tlb"); [ uuid(CC51EFFE-C8F4-40FA-AEA3-EB6D1D89926E) ] coclass MyStruct { [default] interface IMyStruct; }; };

  • Agregar implementación:

STDMETHODIMP CMyStruct::getAge(LONG* age) { *age = m_age; return S_OK; } STDMETHODIMP CMyStruct::setAge(LONG age) { m_age = age; return S_OK; } STDMETHODIMP CMyStruct::getName(BSTR* name) { *name = SysAllocString(m_name.c_str()); return S_OK; } STDMETHODIMP CMyStruct::setName(BSTR name) { m_name.assign(name); return S_OK; }

  1. Creando cliente Agregue el nuevo proyecto de aplicación de consola Win32 MyStructClient a la solución (ejecutable). Agregar el siguiente código:

#include <iostream> // check for correct path to tlb library. Will create tlh, tli files that provide smart pointers, etc. #import "..//COMStructProvider//Debug//COMStructProvider.tlb" no_namespace named_guid using namespace std; int main() { // initialize COM runtime CoInitialize(NULL); { // smart pointer simplifies work, will invoke CoCreateInstance to activate COM server IMyStructPtr spMyStruct(__uuidof(MyStruct)); BSTR name = SysAllocString(L"John"); spMyStruct->setName(name); SysFreeString(name); BSTR retreivedName; spMyStruct->getName(&retreivedName); wcout << "name " << retreivedName << endl; SysFreeString(retreivedName); spMyStruct->setAge(5); long age = 0; spMyStruct->getAge(&age); cout << "age " << age << endl; } CoUninitialize(); return 0; }

Entonces, tiene dos procesos ejecutándose simultáneamente: servidor que proporciona acceso a la estructura y al cliente que tiene acceso a la misma estructura (puede ejecutar más procesos de cliente en paralelo. Todos los clientes acceden al mismo proceso de servidor, puede considerarse como singleton) posible generar un proceso separado con cada activación). El cliente puede cambiar y obtener valores de esta estructura (como se requería). Bajo el capó, el cliente tiene acceso al proxy de coclass en su propio espacio de direcciones y el tiempo de ejecución COM soporta todas las comunicaciones entre procesos. Esos proxy / stubs (en forma de fuentes C / C ++) son generados por el compilador MIDL desde el archivo idl de interfaz mencionado anteriormente. En lo que respecta a la transferencia de datos entre dos procesos , debe saber que existen tres tipos de referencias COM: personalizadas, estándar y universales. En este ejemplo, universal es suficiente porque utilizo solo tipos VARIANT compatibles como parámetros de método. Para pasar tipos arbitrarios, debe usar referencias estándar (con ayuda de proxy / stub dlls, generados en proyectos separados en el primer paso al crear el servidor COM. Nombre del proyecto es el nombre del proyecto con servidor con sufijo PS). Desventaja de la clasificación estándar: debe implementar esos dlls PS con su servidor COM.

Tengo un conocimiento promedio en COM y me gustaría entender cómo COM ayuda en la transferencia de datos. Asumiendo que hay dos procesos, Proceso-A y Proceso-B y ambos quieren compartir algunos datos entre ellos, por supuesto que hay muchos mecanismos RPC pero me gustaría usar COM.

  1. no puede crear un dll COM porque entonces sería específico de procesar y no se puede usar
  2. ¿Podemos crear un servidor COM COM de Single ton y envolver la estructura en COM CoClass y exponer sus miembros como propiedades y luego ... sin idea de cómo hacerlo?

Arriba, entiendo, ¿alguno de ustedes puede ayudarme a aclarar mi entendimiento sobre este tema? Básicamente, me gustaría compartir una estructura de datos entre dos procesos utilizando COM


Los servidores fuera de proceso COM exe son notablemente difíciles de escribir, pero Microsoft ha creado el servicio COM + Component para solucionar esto.

Contiene muchos servicios, pero aquí nos interesa el servicio de Aplicación que le permite alojar servidores en proceso (DLL) en un host sustituto fuera de proceso.

Es bastante simple, solo escriba una DLL ATL estándar (o use cualquier otro lenguaje / framework que desee). Recomiendo usar tipos de automatización para la interfaz, por lo que no necesita proxies especiales, por ejemplo, con una interfaz IDL definida así:

interface ISharedMap : IDispatch{ [id(1)] HRESULT PutData([in] BSTR key, [in] VARIANT value); [id(2)] HRESULT GetData([in] BSTR key, [out, retval] VARIANT *pValue); };

A continuación, cree una nueva aplicación COM +, como se describe aquí: Creación de aplicaciones COM + , y declaración como una aplicación de servidor. Esto es lo que deberías ver una vez que esto esté hecho:

Su DLL ahora se alojará automáticamente en un proceso específico (el famoso dllhost.exe ) que se iniciará tan pronto como los clientes intenten conectarse. De forma predeterminada, el mismo proceso se utilizará para varios clientes COM fuera de proceso. Se apagará después de un tiempo, pero puede configurar la aplicación COM + de varias maneras, por ejemplo, con el indicador '' Dejar correr cuando está inactivo '':

Ahora podrá usar su caché de memoria de proceso cruzado para todos los clientes COM que le gusten, por ejemplo, así desde un simple código javascript .js:

var map = new ActiveXObject("SharedMap"); map.PutData("mykey", "mydata") var data = map.GetData("mykey")

Nota: la implementación del caché se deja al lector, pero podría reutilizar otro de los servicios COM +: el Administrador de propiedades compartidas COM +