Я пытаюсь создать внекорпусный com-сервер в каком-нибудь exe-файле и клиенте, который будет получать доступ к функциям через proxy\stub
механизм.
У меня есть файл .idl:
[
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 файлов, создан прокси \ stub dll с использованием .def:
LIBRARY proxy_stub.dll
DESCRIPTION 'generic proxy/stub DLL'
EXPORTS DllGetClassObject @1 PRIVATE
DllCanUnloadNow @2 PRIVATE
DllRegisterServer @4 PRIVATE
DllUnregisterServer @5 PRIVATE
Тогда я зарегистрировал эту DLL, используя regsrv32
и в реестре win у меня есть это:
На моем сервере я создал фабрику:
CoRegisterClassObject(CLSID_InterractionInterfaceFactory, (IClassFactory*) &factory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, ®ID);
И это ждет клиентских звонков.
В клиенте я называю свою фабрику, используя 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 или нет? Может быть, я забыл несколько шагов? Почему мой объект не может пройти через границы процесса?
Редактировать:
Я попытался заменить клиентский код, и теперь это:
result = CoCreateInstance(CLSID_InterractionInterfaceFactory, NULL, CLSCTX_LOCAL_SERVER, IID_InterractionInterface, (void**)&iface);
iface->Test(1);
И когда я пытаюсь вызвать Test (1), он выдает ошибку, что это чисто виртуальная функция. И на фабрике в CreateInstance я получаю требование интерфейса Unkonown.
Если вы хотите использовать прокси / заглушку DLL, определите интерфейс вне library
блок. Только вещи, определенные за пределами library
идет в код, сгенерированный для прокси / заглушки DLL. Материал, определенный или на который есть ссылка, внутри library
Блок переходит в сгенерированную библиотеку типов. Типичный файл IDL определяет интерфейсы вне library
, а затем упоминает их внутри, в coclass
блоки; таким образом, определения интерфейсов заканчиваются как прокси / заглушкой, так и TLB, для максимальной гибкости.
Ваш интерфейс совместим с автоматизацией (ну, почти; измените тип параметра с int на long). В этом случае вы можете предпочесть использовать так называемый «универсальный» маршаллинг, основанный на библиотеке типов. Просто зарегистрируйте сгенерированный MIDL файл TLB с regtlib
инструмент или программно с LoadTypeLibEx
и у вас будет поддержка маршалинга.
Других решений пока нет …