Создание объекта COM в рантайме БЕЗ регистрации *.dll
От: NewEmptyName  
Дата: 21.11.07 08:18
Оценка:
Добрый день всем!
Собственно, сабж. Есть ДЛЛ или ОСХ, нужно создать объек без регистрации библиотеки.
Рабочий пример как это сделать исключительно на ВБ6 я нашел на vbstreets, но создать объект хочу на С++ и вернуть его вызывателю в ВБ. Тут начинаются грабли. С++ код отрабатывает, но в ВБ вызов метода возвращенного объекта , в лучшем случае приводит к выходу из процедуры, в худшем — Access Voilation. Повторюсь, что аналогичный код, написаный на ВБ работает.
Кусок ф-ции создания объекта:


IUnknown* __stdcall CreateObjectFromFile(LPCOLESTR strLibrary, LPCOLESTR strClassName,/*для отладки*/ DWORD * ResPtr)
{
    char s[20];
    //ResPtr = new DWORD [20];
    DWORD i;
    IUnknown*            newobj = NULL;
    IClassFactory*        udtCF;
    GUID                classid;
    //GUID                IID_ClassFactory  = IID_IClassFactory ;
    HMODULE                hModule;
    DLLGETCLASSOBJECT    pFunc;
    COCLASSARR            udtCoCls;
    PCOCLASS            tmpCo;
    DWORD f=0;
    HRESULT hRes;

    if (!GetCoClasses(strLibrary,&udtCoCls)){i=1; goto RetN; //return NULL;}
    
    for (f=0; f<udtCoCls.size(); f++)
    {tmpCo = udtCoCls[f];
       if (wcscmp(strClassName, tmpCo->Name )==0)
     {
       RtlMoveMemory(&classid,&udtCoCls.at(f)->guid,sizeof(GUID));
       break;
     }
    }
    
    if (f == udtCoCls.size()) {i=2;goto RetN;} //return NULL;}
    hModule = GetModuleHandleW(strLibrary);
    if (hModule == 0)
    {
      hModule = LoadLibraryW(strLibrary);
      if (hModule == 0) {i=3; goto RetN;} //return NULL;
    }

    pFunc = (DLLGETCLASSOBJECT)GetProcAddress(hModule,"DllGetClassObject");
    memcpy(&ResPtr[0],&pFunc,4);//debug
    if (pFunc==0) {i=4; goto RetN;} //return NULL;

    hRes = pFunc(classid,IID_ClassFactory,(void**)&udtCF);
    memcpy(&ResPtr[1],&udtCF,4);//debug
    if ( udtCF == NULL){i=5; goto RetN; //return NULL;}
    
    hRes = udtCF->CreateInstance (NULL,IID_IUnknown,(void**)&newobj) ;
    if (hRes != 0)    {udtCF->Release ();i=6;    goto RetN; //return NULL;}

        memcpy(&ResPtr[2],&newobj,4);//debug
    udtCF->Release();

  return (newobj);

RetN:
  sprintf((char*)&s,"Err i=%u",i);
  MessageBox (NULL,(char*)&s,"",MB_OK);
  return NULL;
}


и не работает
Не страшно, если ты один.
Страшно — если ты ноль.
Re: Создание объекта COM в рантайме БЕЗ регистрации *.dll
От: ZAMUNDA Земля для жалоб и предложений
Дата: 21.11.07 09:22
Оценка: -1
Здравствуйте, NewEmptyName, Вы писали:

IUnknown** __stdcall CreateObjectFromFile(LPCOLESTR strLibrary, LPCOLESTR strClassName,/*для отладки*/ DWORD* ResPtr)
{
;/*blah blah blah*/;
}
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Re[2]: Создание объекта COM в рантайме БЕЗ регистрации *.dll
От: NewEmptyName  
Дата: 21.11.07 10:09
Оценка:
Здравствуйте, ZAMUNDA, Вы писали:

ZAM>Здравствуйте, NewEmptyName, Вы писали:


ZAM>
ZAM>IUnknown** __stdcall CreateObjectFromFile(LPCOLESTR strLibrary, LPCOLESTR strClassName,/*для отладки*/ DWORD* ResPtr)
ZAM>{
ZAM>;/*blah blah blah*/;
ZAM>}
ZAM>


Не уверен. Судя по всему, StdOle.IUnknown (в VB6) соответствует IUnknown*. такой вывод я сделал, в частности, исходя из вот таких строк:
Public Function CreateObjectFromFile1(ByVal strLibrary As String, ByVal strClassName As String) As stdole.IUnknown
  Dim newobj              As stdole.IUnknown
'................
    Call CallPointer (udtCF.CreateInstance, obj, 0, VarPtr(IID_IUnknown), VarPtr(newobj))  'VarPtr(newobj) equ IUnknown** ???
'................
    Set CreateObjectFromFile1 = newobj
End Function


вызыватель делает:

Dim o as object
  Set o = CreateObjectFromFile1 ("MyTest.dll", "clsTestClass")
  o.TestMetod ("123")

и как-бы работает....
Не страшно, если ты один.
Страшно — если ты ноль.
Re[3]: Создание объекта COM в рантайме БЕЗ регистрации *.dll
От: ZAMUNDA Земля для жалоб и предложений
Дата: 21.11.07 10:53
Оценка:
Здравствуйте, NewEmptyName, Вы писали:

NEN>Здравствуйте, ZAMUNDA, Вы писали:

NEN>Не уверен. Судя по всему, StdOle.IUnknown (в VB6) соответствует IUnknown*. такой вывод я сделал, в частности, исходя из вот таких строк:
И хоть ваш вывод верен, но всётаки я настаиваю
Автор: ZAMUNDA
Дата: 21.09.05
на том что в данном случае он является софизмом.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Re[3]: Для справки.
От: ZAMUNDA Земля для жалоб и предложений
Дата: 21.11.07 11:01
Оценка:
Здравствуйте, NewEmptyName, Вы писали:

NEN>
NEN>Public Function CreateObjectFromFile1(ByVal strLibrary As String, ByVal strClassName As String) As stdole.IUnknown
NEN>  Dim newobj              As stdole.IUnknown
NEN>'................
NEN>    Call CallPointer (udtCF.CreateInstance, obj, 0, VarPtr(IID_IUnknown), VarPtr(newobj))  'VarPtr(newobj) equ IUnknown** ??? VarPtr(newobj) equ IUnknown**, ObjPtr(newobj) equ IUnknown*
NEN>'................
NEN>    Set CreateObjectFromFile1 = newobj
NEN>End Function
NEN>


Вот интересный примерчик:
Dim obj as Object

debug.print hex$(VarPtr(obj)) ; ":" hex$(ObjPtr(obj))
set obj = new Collection
debug.print hex$(VarPtr(obj)) ; ":" hex$(ObjPtr(obj))
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Re: Создание объекта COM в рантайме БЕЗ регистрации *.dll
От: Vi2 Удмуртия http://www.adem.ru
Дата: 21.11.07 11:02
Оценка:
Здравствуйте, NewEmptyName, Вы писали:

NEN>Собственно, сабж. Есть ДЛЛ или ОСХ, нужно создать объек без регистрации библиотеки.

NEN>Рабочий пример как это сделать исключительно на ВБ6 я нашел на vbstreets, но создать объект хочу на С++ и вернуть его вызывателю в ВБ. Тут начинаются грабли. С++ код отрабатывает, но в ВБ вызов метода возвращенного объекта , в лучшем случае приводит к выходу из процедуры, в худшем — Access Voilation. Повторюсь, что аналогичный код, написаный на ВБ работает.
NEN>...
NEN>и не работает

Приведи declare-код на VB, который определяет CreateObjectFromFile.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Создание объекта COM в рантайме БЕЗ регистрации *.dll
От: NewEmptyName  
Дата: 21.11.07 12:43
Оценка:
Здравствуйте, Vi2, Вы писали:
Vi2>Приведи declare-код на VB, который определяет CreateObjectFromFile.

Сейчас декларация выглядит так:

Private Declare Function CreateObjectFromFile Lib "D:\WorkFlow\OrderFW\OrderFW\Debug\OrderFW.dll" (ByVal strLibrary As String, ByVal strClassName As String, ByVal ArrayDwordsPtr20 As Long) As Object


Функция выглядит так:

IUnknown** __stdcall CreateObjectFromFile(LPCOLESTR strLibrary, LPCOLESTR strClassName, DWORD * ResPtr)
{
  IUnknown**    newobj =new IUnknown* ;// NULL;
//.......
    CreateInstance (NULL,IID_IUnknown,(void**)newobj) ;
//.......  

  return (newobj);
}


вызыватель:

  Dim nObj As Object
    Set nObj = CreateObjectFromFile(s1, s2, VarPtr(a(0)))
    nObj.TestMethod("123") 'ашыпка


проверку возвр. значений ф-ций, само собой, делаю, просто не привел чтоб не нагромождать код. указатель на инстанс я получаю... только дальше...
я явно где-то тут элементарно затупил.. надо взгляд со стороны
Не страшно, если ты один.
Страшно — если ты ноль.
Re[3]: Создание объекта COM в рантайме БЕЗ регистрации *.dll
От: NewEmptyName  
Дата: 21.11.07 12:55
Оценка:
И еще вариант , который работает:


Private Declare Function CreateObjectFromFile1 Lib "D:\WorkFlow\OrderFW\OrderFW\Debug\OrderFW.dll" (ByVal strLibrary As String, ByVal strClassName As String) As stdole.IUnknown


IUnknown* __stdcall CreateObjectFromFile1(LPCOLESTR strLibrary, LPCOLESTR strClassName)
{
  IUnknown*        newobj;
  //............
  udtCF->CreateInstance (NULL,IID_IUnknown,(void**)&newobj);
  //............
  return (newobj);
}


вызыватель:

    Dim objCtrl As Object
    Dim objCtrl1 As stdole.IUnknown

      Set objCtrl1 = CreateObjectFromFile1(s1, s2)
      Set objCtrl = objCtrl1
      objCtrl.TestMethod ("123")'так работает..  :xz:


то что работает — это хорошо, а вот то что я не понял каким образом так получается с Set — соотв. плохо.
хочется сразу вернуть объект. да , собственно не понятно почему просто вот так не работает ?
  Dim objCtrl As Object
    Set objCtrl = CreateObjectFromFile1(s1, s2) 
    objCtrl.TestMethod ("123")'не работает
Не страшно, если ты один.
Страшно — если ты ноль.
Re[3]: Создание объекта COM в рантайме БЕЗ регистрации *.dll
От: Vi2 Удмуртия http://www.adem.ru
Дата: 21.11.07 13:09
Оценка:
Здравствуйте, NewEmptyName, Вы писали:

NEN>Сейчас декларация выглядит так:


Я так и думал.
NEN>Private Declare Function CreateObjectFromFile Lib "D:\WorkFlow\OrderFW\OrderFW\Debug\OrderFW.dll" (ByVal strLibrary As String, ByVal strClassName As String, ByVal ArrayDwordsPtr20 As Long) As Object


Т.е. считается, что функция возвращает IDispatch интерфейс, поэтому VB не проверяет и не запрашивает специально этот интерфейс. А Object и есть IDispatch*.

NEN>Функция выглядит так:


Неправильно. Лишняя косвенность не нужна, нужно правильно передать нужный интерфейс.

NEN>// IUnknown** __stdcall CreateObjectFromFile(LPCOLESTR strLibrary, LPCOLESTR strClassName, DWORD * ResPtr)
Vi2>>IDispatch* __stdcall CreateObjectFromFile(LPCOLESTR strLibrary, LPCOLESTR strClassName, DWORD * ResPtr)
NEN>{
NEN>//  IUnknown**    newobj =new IUnknown* ;// NULL;
Vi2>  IDispatch*    newobj = NULL;
NEN>//.......
NEN>//    CreateInstance (NULL,IID_IUnknown,(void**)newobj) ;
NEN>    CreateInstance (NULL,IID_IDispatch,(void**)newobj) ;
NEN>//.......  

NEN>  return (newobj);
NEN>}
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Создание объекта COM в рантайме БЕЗ регистрации *.dll
От: Vi2 Удмуртия http://www.adem.ru
Дата: 21.11.07 13:16
Оценка: 11 (2)
Здравствуйте, NewEmptyName, Вы писали:

NEN>И еще вариант , который работает:

NEN>Private Declare Function CreateObjectFromFile1 Lib "D:\WorkFlow\OrderFW\OrderFW\Debug\OrderFW.dll" (ByVal strLibrary As String, ByVal strClassName As String) As stdole.IUnknown

NEN>  Dim objCtrl As Object
NEN>    Set objCtrl = CreateObjectFromFile1(s1, s2) 
NEN>    objCtrl.TestMethod ("123")'не работает

Это должно работать, т.к. VB запросит нужный интерфейс, потому что stdole.IUnknown и Object не одинаковы, и их нужно привести через QueryInterface, что VB и сделает. Простое указание Declare ... As Object не пройдет, т.к. реально передается IUnknown интерфейс, в виртуальной таблице которого нет необходимых функций, нужных для реализации вызова "TestMethod".
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Создание объекта COM в рантайме БЕЗ регистрации *.dll
От: NewEmptyName  
Дата: 21.11.07 14:23
Оценка:
Спасибо за разъяснения! все получилось!
Не страшно, если ты один.
Страшно — если ты ноль.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.