CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 2 FirstFirst 12
Results 16 to 21 of 21
  1. #16
    Join Date
    Apr 2004
    Posts
    10
    My program works well. But, I don't know if it's the same kind of control than yours.

    My DLL opens and closes RTP/RTCP audio streams between two machines. To do that, it builds a directshow graph with several filters and the soundcard.
    I've run the app and it works.

    Hope it'll help.

  2. #17
    Join Date
    Mar 2002
    Location
    Philadelphia
    Posts
    150
    je16noutch,

    Why create a new DirectShow Filter DLL at all? Presumably the pre-existing filters pre-exist in other DLLs.

    A straight ATL COM DLL will export DLLGetClassObject() and use the ATL object map to instantiate their class factories which in turn are used to create COM objects, i.e.:
    Code:
    BEGIN_OBJECT_MAP(ObjectMap)
    OBJECT_ENTRY(CLSID_MyDSFilter, CMyDSFilter)
    END_OBJECT_MAP()
    The problem is, there is no standard way to pass initialization information to class factories implemented via the ATL object map. So Direct Show uses
    Code:
    CFactoryTemplate g_Templates[] = {
        {
        //...
            &sudFilterReg                   // Pointer to filter information.
        }
    to pass additionaly information to its class factory via sudFilterReg. It is not clear to me how Direct Show uses g_Templates[] from DllGetClassObject().

    What additional code in your DLL does Direct Show supply to implement DLLGetClassObject()? That code must be using g_Templates[]. Search for m_pAMoveSetup_Filter in your code and set it to NULL instead of g_Templates.
    Sincerely,
    - Ron

  3. #18
    Join Date
    Apr 2004
    Posts
    10
    The thing is that I need to build a DLL to plug it in the software of my company.

    The point of my DLL is to open RTP Audio streams and to manage the audio configuration. So I don't think that something like that already exists.

    I couldn't find "m_pAMoveSetup_Filter" in my code.

    I guess the library "Strmbasd.lib" which launched the link error at the beginning needs to find a g_Templates array in case of new filters. Since, there are no filters like this in my program, the empty array is not use and so it works.
    But still, you're right, it's strange.

    I've looked at ATL and the macros you mentionned... That's what made me try to pass the problem like this !

    But I don't know how my first project (the MFC) worked and which DllGetClassObject() it was using...

  4. #19
    Join Date
    Mar 2002
    Location
    Philadelphia
    Posts
    150
    Was your first program an MFC Exe or DLL? How did it include Direct Show?
    Sincerely,
    - Ron

  5. #20
    Join Date
    Jul 2001
    Location
    Viet Nam
    Posts
    132
    Template factory is used to create/query COM/ActiveX object, the DLL of "je16noutch" does not export any control, so CFactoryTemplate in this case is nothing.

    I think, if his DLL intend to export COM object, that DLL will not work, DllGetClassObject() cannot use CFactoryTemplate because that class does not correct.

  6. #21
    Join Date
    Feb 2002
    Posts
    8

    Same prob + details

    Ah, after some googling this seems to be a recurring problem for people (although I have not yet found solutions that work for me)

    Detailed description of what happens to me (which I think is almost exactly what the original poster had):

    I am writing a ocx component with Visual C++ 6.0SP4
    The component itself uses DirectX 9, DirectShow filters etc. using a linked in statically linked library "My.lib". Note that it just uses some filters, it does not expose or export any DirectShow filter functionality directly.
    I want to use the component as a control in Visual Basic 2003/.net

    The VC++ project wizard I used was the "MFC ActiveX ControlWizard" which creates code & files that - on their own - compile, link, and instantiate just fine in VB 2003/.net

    But as soon as I link in the "My.lib" with all my DirectX functions (which I have previously successfully used in MFC and non-MFC applications but not yet in DLLs like an ocx control) I get these errors:

    VideoLib.lib(dllentry.obj) : error LNK2001: unresolved external symbol "class CFactoryTemplate * g_Templates" (?g_Templates@@3PAVCFactoryTemplate@@A)
    VideoLib.lib(dllentry.obj) : error LNK2001: unresolved external symbol "int g_cTemplates" (?g_cTemplates@@3HA)


    As per MSDN, the template mechanism is used by a DirectX subclass of CClassFactory which is data driven (via the templates, declaring each available object, its creation method pointer, GUID, and some extra stuff). In my lib and other applications I always instantiate my filter subclasses directly (via new CMyFilter() etc.) not via DllGetClassObject which does a GUID lookup in the template array. So I actually get away with not declaring the g_Templates global at all. (My.lib is bundled up as a static lib)

    Somehow, the Wizard generated ActiveX component files now DO require that global to exist, but what objects should I be declaring in there ?
    • My DShow filters ? no-they are never instantiated via GUIDs / factories
    • The COleControl subclass I am building ? No- it is not a DirectShow class deriving from CUnknown, so I cannot declare it in the template.
    • You can shut up the linker errors by setting g_Templates to NULL and g_cTemplates to 0. A similar method - setting all the params of a single fake template to NULL - was also suggested in a different codeguru thread, but unfortunately it does not work for me at least...either method will give a Object Reference not set to an instance of an object. error in Visual Basic when you try to instantiate one of these and it will actually hard crash the ActiveX Test Container App in Visual Studio, so that wont do. Likewise, when I use oleview.exe to check out my control (Start>Run...>oleview, then in the left hand side tree view, open Object Classes>Grouped by Component Category>Control>your control class name, whatever was specified in the IMPLEMENT_OLECREATE_EX macro. Then click on the little + sign to try to instantiate the control. I get a CoGetClassObject failed. The specified module could not be found. etc. error.)

    If I revert to just the basic Wizard generated skeleton (dont link w my.lib, dont call any of its functions), the ocx functions just fine. I can instantiate it in VB2003, get/set parameters, etc.

    The cat that drags in the g_Templates/g_cTemplates symbols is strmbase.lib (or strmbasd.lib for debug builds). The CFactoryTemplate class itself is defined in the DirectX include file combase.h (include streams.h)

    But I can't figure out
    • why I need to suddenly declare them in my ActiveX Component Build (whereas in app builds or the static lib build I didn't) and second
    • what I should be filling the CFactoryTemplate WITH

    I think a significant clue is the line
    "If a call to the CoGetClassObject function finds the class object that is to be loaded in a DLL, CoGetClassObject uses the DLL's exported DllGetClassObject function. "
    from MSDN's DllGetClassObject documentation..
    I interpret this as "when creating a normal application or static library, CoGetClassObject generates the object differently than when creating a DLL/ocx. In the latter case, it gives the DLL control over object creation"
    If you check in the Wizard generated .def file, you will indeed see a line exporting a DllGetClassObject function. I cannot however find an implementation of it in my Wizard generated files.
    I speculate that use of the IMPLEMENT_OLECREATE_EX macro in your xxxCtrl.cpp file has something to do with that (it is defined in VC98/MFC/Include/AFXCTL.H).

    <ripping some hair>
    <rapidly graying the rest>

    Any suggestions would be very helpful/welcome !
    Thanks in advance

    The Solution

    Thanks to Google groups search and Paul Wissenbach - quoting from his post:

    The problem exists because you end up linking in strmbase.lib which has entry points functions for DllGetClassObject() and DllCanUnloadNow() among others. You really don't want these entry points
    defined in for your ActiveX control. They are designed for DirectShow filters, and require g_Templates to be defined by your filter.

    One solution is to override the following functions by implementing them into your ActiveX control yourself. That way you don't pull in the ones from the DShow.

    Regards,


    Paul
    Code:
    /////////////////////////////////////////////////////////////////////////////
    // DllGetClassObject
    
    extern "C"
    STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
    {
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     return AfxDllGetClassObject(rclsid, riid, ppv);
    }
    
    /////////////////////////////////////////////////////////////////////////////
    // DllCanUnloadNow
    
    extern "C"
    STDAPI DllCanUnloadNow(void)
    {
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     return AfxDllCanUnloadNow();
    }

    My hero ! The code compiles and links without farting, and it instantiates just fine in Visual Basic too !
    Last edited by rseidl; July 6th, 2004 at 06:48 AM.

Page 2 of 2 FirstFirst 12

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured