2013-08-02 4 views
1

Я пытаюсь создать out-of-proc com-сервер в некотором exe-файле и клиенте, который будет обращаться к функциям через механизм proxy\stub. У меня есть IDL-файл:C++ COM out-of-proc marshalling data через proxy stub

[ 
    object, 
    uuid(eaa27f4f-ad6b-4a52-90f3-6028507751a1), 
    dual, 
    nonextensible, 
    helpstring("IConfig Interface"), 
    pointer_default(unique) 
] 
interface IInterractionInterface : IDispatch 
{ 
    [id(1), helpstring("Testing function")] HRESULT Test([in] long param); 
}; 


[ 
    uuid(6fde5037-3034-4ae1-8aa7-2ad45e5716e4), 
    version(1.0), 
    helpstring("Some lib") 
] 
library SomeLib 
{ 
    importlib("stdole32.tlb"); 
    importlib("stdole2.tlb"); 

    [ 
     uuid(86feabe4-a0a7-45b5-bcd4-f4f7085d6b1f), 
     helpstring("Some lib") 
    ] 
    coclass Interraction 
    { 
     [default] interface IInterractionInterface; 
    }; 
} 

Я сгенерирована с помощью компилятора MIDL _p.c, _i.c файлы, созданные прокси \ DLL-заглушки с помощью .def:

LIBRARY  proxy_stub.dll 
DESCRIPTION 'generic proxy/stub DLL' 
EXPORTS  DllGetClassObject  @1 PRIVATE 
       DllCanUnloadNow  @2 PRIVATE 
       DllRegisterServer  @4 PRIVATE 
       DllUnregisterServer @5 PRIVATE 

Тогда я зарегистрирован это дллы с помощью regsrv32, и в выигрыше реестре у меня есть это: enter image description here

в моем сервере я создал завод:

CoRegisterClassObject(CLSID_InterractionInterfaceFactory, (IClassFactory*) &factory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &regID); 

И он ждет звонков клиентов. В клиенте я зову свою фабрику, используя CreateInstance:

result = CoGetClassObject(CLSID_InterractionInterfaceFactory, CLSCTX_LOCAL_SERVER, NULL, IID_IClassFactory, (void**)&factory); 

if (S_OK == result) 
{ 
    IInterractionInterface* iface = NULL; 

    result = factory->CreateInstance(NULL, IID_InterractionInterface, (void**)&iface); 
    if (S_OK == result) 
    { 

    } 
} 

И клиент получает нулевую Iface и результат является E_UNEXPECTED, но на заводе, он создает и успешно я возвращал S_OK от фабрики :: CreateInstance(). Я не могу понять, есть ли механизм PS, используя мою .dll или нет? Может, я забыл несколько шагов? Почему мой объект не может проходить через границы процесса?

Edit: Я пытался заменить код клиента и теперь это:

result = CoCreateInstance(CLSID_InterractionInterfaceFactory, NULL, CLSCTX_LOCAL_SERVER, IID_InterractionInterface, (void**)&iface); 
iface->Test(1); 

И когда я пытаюсь вызвать Test (1) он выдает ошибку, что это является чистой виртуальной функцией. И на фабрике в CreateInstance я получаю требование интерфейса Unkonown.

+0

Использование прокси-сервера требует записи раздела реестра в 'HCKR \ Interfaces', значение ProxyStubClsId32 должно быть установлено в CLSID для прокси-сервера. Не ясно, было ли это сделано правильно. E_UNEXPECTED, однако, не такая ошибка, которую вы ожидаете, когда у вас возникнут проблемы с регистрацией, вместо этого вы получите E_NOINTERFACE. Попробуйте использовать ProcMon SysInternals, вы можете получить более четкое представление о том, что происходит не так. Может быть, проблема с загрузкой DLL. –

+0

Этот путь на снимке экрана не указан HKEY_CLASSES_TOOR \ Wow6432Node \ CLSID \ {GUID}. Это не правильно? – fryme

+0

Это правильно, только не единственный. Вам также нужны * дополнительные * ключи, по одному в «HKCR \ Interfaces» для каждого интерфейса, реализованного сервером. Вот как COM выясняет, какой сервер необходимо использовать, когда его просят маршалировать интерфейс. Вы можете легко это увидеть в ProcMon, рекомендуется. –

ответ

2

Если вы хотите использовать прокси/заглушку DLL, определите интерфейс за пределами блока library. Только материал, указанный за пределами library, вносится в код, сгенерированный для DLL прокси/заглушки. Материал, определенный или ссылка, внутри блока library переходит в библиотеку сгенерированного типа. Типичный IDL-файл определяет интерфейсы за пределами library, а затем упоминает их внутри, в coclass блоках; таким образом, определения интерфейсов заканчиваются как для прокси/заглушки, так и для TLB, для максимальной гибкости.

Ваш интерфейс совместим с системой (ну, почти, измените тип параметра от int до long). В этом случае вы можете использовать так называемую «универсальную» сортировку, основанную на библиотеке типов. Просто зарегистрируйте файл TLB, созданный MIDL, с помощью инструмента regtlib или программно с LoadTypeLibEx, и у вас будет поддержка маршалинга на месте.

+0

Я обновляю свой вопрос. Я определяю интерфейс за пределами библиотечного блока в .idl-файле. Затем я зарегистрирован в regtlib, как вы говорите, и внес некоторые изменения в код клиента (посмотрите на нижнюю часть сообщения). И теперь у меня есть ошибка, которую функция, которую я пытаюсь назвать, является чистой виртуальной. Я думаю, это потому, что он запрашивает Неизвестный интерфейс. – fryme

+0

Почему вы внесли это изменение в код клиента? Фактически ли объект фабрики класса реализует «IInterractionInterface»? Это было бы необычно: обычно фабрика классов реализует 'IClassFactory', а реализация' CreateInstance' создает новый объект, который, в свою очередь, реализует желаемый интерфейс. –