Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to instantiate an [appobject] coclass

15 views
Skip to first unread message

Barzo

unread,
Oct 9, 2009, 9:18:22 AM10/9/09
to
Hi,

in my DLL I have a coclass defined with [appobject] attribute:

-------------------------------------------------------------------------------
[
object,
uuid(AB566C82-AF54-11DE-B5BE-00A0D15E9B20),
dual,
nonextensible,
helpstring("IAudioLib Interface"),
hidden,
pointer_default(unique)
]
interface IAudioLib : IDispatch
{
[id(1), helpstring("Retrieve the library version.")]
HRESULT GetLibVersion([out, retval] BSTR* pVal);
[id(2), helpstring("Retrieve the error description.")]
HRESULT RetValToStr([in] E_AUDIOLIB_RET_VAL rv, [out, retval] BSTR*
pVal);
[id(3), helpstring("Retrieve the number of devices for a specific
API.")]
HRESULT GetDeviceCount([in] E_AUDIO_API audio_api, [out, retval]
short* pVal);
[id(4), helpstring("Retrieve the informations of a single device.")]
HRESULT GetDeviceInfo([in] long device,
[in] E_AUDIO_API audio_api,
[in, out] T_DeviceInfo* retDevInfo,
[out, retval] E_AUDIOLIB_RET_VAL* pVal);
[id(5), helpstring("Retreive an array containing informations for
all devices.")]
HRESULT GetDevicesInfo([in] E_AUDIO_API audio_api, [out, retval]
SAFEARRAY(T_DeviceInfo)* pVal);
};
....
....
[
uuid(AB566C81-AF54-11DE-B5BE-00A0D15E9B20),
appobject,
helpstring("AudioLib Class")
]
coclass AudioLib
{
[default] interface IAudioLib;
};
-------------------------------------------------------------------------------

I have implemented all the IAudioLib methods in AudioLib.cpp but, in
VB6, when I call a method:

MgsBox AxAudioLib4.GetLibVersion

I get the error:
Runtime Error 429, "ActiveX component can't create object"

This kind of classes have to be implemented (or created) in a special
way?

Thanks,
Daniele.

Drew

unread,
Oct 9, 2009, 2:20:02 PM10/9/09
to

"Barzo" <dba...@gmail.com> wrote in message
news:aa9a107b-b9d3-431d...@k33g2000yqa.googlegroups.com...

--------------------
What is AxAudioLib4? I'll have to assume it's something like:

Dim AxAudioLib4 as NameOfCOMLibrary.AudioLib

and somewhere before you call AxAudioLib4.GetLibVersion you've done this:

Set AxAudioLib4 = new NameOfCOMLibrary.AudioLib

If either of the above is incorrect then that's your problem.

Drew

Igor Tandetnik

unread,
Oct 9, 2009, 2:43:26 PM10/9/09
to
Drew <d...@dam.com> wrote:
> What is AxAudioLib4?

Most likely, the name of the type library, as given by "library" statement.

> I'll have to assume it's something like:
>
> Dim AxAudioLib4 as NameOfCOMLibrary.AudioLib
>
> and somewhere before you call AxAudioLib4.GetLibVersion you've done
> this:
> Set AxAudioLib4 = new NameOfCOMLibrary.AudioLib
>
> If either of the above is incorrect then that's your problem.

Read about [appobject] attribute. It basically instructs VB to create an instance of the class automatically, and to make it
available under the library name.

The real question is, why can't VB create an instance of the class. The OP will have to debug that.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going
to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925

Barzo

unread,
Oct 10, 2009, 11:20:22 AM10/10/09
to
On 9 Ott, 20:43, "Igor Tandetnik" <itandet...@mvps.org> wrote:
>
> Most likely, the name of the type library, as given by "library" statement.

Yes, it is! :-P


>
> Read about [appobject] attribute. It basically instructs VB to create an instance of the class automatically, and to make it
> available under the library name.
>
> The real question is, why can't VB create an instance of the class. The OP will have to debug that.


I don't know why this happens.
I implemented the IAudioLib interface like any classes and while the
other classes works fine, this one cannot be instantiated!
This is the code:

====================================================================
AudioLib.h


class ATL_NO_VTABLE CAudioLib :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CAudioLib, &CLSID_AudioLib>,
public IDispatchImpl<IAudioLib, &IID_IAudioLib, &LIBID_AxAudioLib4, /
*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CAudioLib()
{
}

DECLARE_REGISTRY_RESOURCEID(IDR_AUDIOLIB)


BEGIN_COM_MAP(CAudioLib)
COM_INTERFACE_ENTRY(IAudioLib)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

DECLARE_PROTECT_FINAL_CONSTRUCT()

HRESULT FinalConstruct()
{
return S_OK;
}

void FinalRelease()
{
}

public:
STDMETHOD (GetLibVersion)(/*[out, retval]*/ BSTR* pVal);
STDMETHOD (RetValToStr)(/*[in]*/ E_AUDIOLIB_RET_VAL rv, /*[out,
retval]*/ BSTR* pVal);
STDMETHOD (GetDeviceCount)(/*[in]*/ E_AUDIO_API audio_api, /*[out,
retval]*/ short* pVal);
STDMETHOD (GetDeviceInfo)(/*[in]*/ long device,
/*[in]*/ E_AUDIO_API audio_api,
/*[in, out]*/ T_DeviceInfo* retDevInfo,
/*[out, retval]*/ E_AUDIOLIB_RET_VAL*
pVal);
STDMETHOD (GetDevicesInfo)(/*[in]*/ E_AUDIO_API audio_api, /*[out,
retval]*/ SAFEARRAY** pVal);
};

OBJECT_ENTRY_AUTO(__uuidof(AudioLib), CAudioLib)


====================================================================
AudioLib.cpp

#include "stdafx.h"
#include "AudioLib.h"
#include "Utility.h"


STDMETHODIMP CAudioLib::GetLibVersion(BSTR* pVal)
{
if (pVal) {
_bstr_t* sv = new _bstr_t(AUDIOLIB_VERSION);
*pVal = sv->Detach();
}
return S_OK;
}

//------------------------------------------------------------------------------

STDMETHODIMP CAudioLib::RetValToStr(E_AUDIOLIB_RET_VAL rv, BSTR* pVal)
{
if (pVal) {
_bstr_t* sv = new _bstr_t( EuroAudioLib::RetValToStr
(static_cast<EuroAudioLib::EAudioLibRetVal>(rv)) );
*pVal = sv->Detach();
}
return S_OK;
}

//------------------------------------------------------------------------------

STDMETHODIMP CAudioLib::GetDeviceCount(E_AUDIO_API audio_api, short*
pVal)
{
if (pVal)
*pVal = EuroAudioLib::GetDeviceCount(static_cast<RtAudio::Api>
(audio_api));
return S_OK;
}

//------------------------------------------------------------------------------

STDMETHODIMP CAudioLib::GetDeviceInfo(long device,
E_AUDIO_API audio_api,
T_DeviceInfo* retDevInfo,
E_AUDIOLIB_RET_VAL* pVal)
{
if (retDevInfo)
{
RtAudio::DeviceInfo info;
long retval = EuroAudioLib::GetDeviceInfo(device,
static_cast<RtAudio::Api>
(audio_api),
&info);
// Convert from RtAudio::DeviceInfo to T_DeviceInfo
ConvertFromDeviceInfo(retDevInfo, &info);

if (pVal) *pVal = static_cast<E_AUDIOLIB_RET_VAL>(retval);
}
return S_OK;
}

//------------------------------------------------------------------------------

STDMETHODIMP CAudioLib::GetDevicesInfo(E_AUDIO_API audio_api,
SAFEARRAY** pVal)
{
SAFEARRAYBOUND sab;
IRecordInfo* pRecordInfo = NULL;
T_DeviceInfo* pinfo;

EuroAudioLib::DeviceInfoList info_list;
EuroAudioLib::DeviceInfoList::iterator info_it;

//Retreive the list of informations
EuroAudioLib::GetDevicesInfo(static_cast<RtAudio::Api>(audio_api),
&info_list);

sab.lLbound = 0;
sab.cElements = info_list.size();

// Filled an information structure in order to create the table
HRESULT hr = GetRecordInfoFromGuids(LIBID_AxAudioLib4,
1, // uVerMajor
0, // uVerMinor
GetUserDefaultLCID(),
IID_IAudioLib,
&pRecordInfo);

// Destroys the table if it already existed
if (*pVal != NULL)
{
SafeArrayDestroy(*pVal);
*pVal = NULL;
}
// Create an array for transport
*pVal = SafeArrayCreateEx(VT_RECORD, 1, &sab, pRecordInfo);
pRecordInfo->Release();
if (*pVal == NULL)
{
hr = Error(_T("Cannot create the devices info array"));
return hr;
}

hr = SafeArrayAccessData(*pVal, (void**)&pinfo);
if (FAILED(hr))
return hr;

// fill in UDT members
uint16_t i = 0;
for(info_it = info_list.begin(); info_it != info_list.end(); info_it+
+)
ConvertFromDeviceInfo(&pinfo[i++], &(*info_it));

hr = SafeArrayUnaccessData(*pVal);
if (FAILED(hr))
{
SafeArrayDestroy(*pVal);
return hr;
}

return S_OK;
}

Drew

unread,
Oct 13, 2009, 11:04:26 AM10/13/09
to
Igor,

Sorry, I don't see a "library" statement; unless you refer to the
helpstring. I've read about (and use) the appobject attribute and yet I
still need to instantiate it explicitly. So I don't quite understand your
point about VB creating the object automagicly. Please enlighten me.

Thanks,
Drew

"Igor Tandetnik" <itand...@mvps.org> wrote in message
news:OgWgkBRS...@TK2MSFTNGP05.phx.gbl...

Igor Tandetnik

unread,
Oct 13, 2009, 3:20:55 PM10/13/09
to
"Drew" <d...@dam.com> wrote in message news:Ohpg8aBT...@TK2MSFTNGP04.phx.gbl

> Sorry, I don't see a "library" statement

It's behind two rows of ellipsis. I made an educated guess about its existence.

> I've read about (and use) the appobject attribute and yet

> still need to instantiate it explicitly. So I don't quite understand your
> point about VB creating the object automagicly. Please enlighten me.

Yes, you seem to be right, [appobject] doesn't quite work the way I expected it to work. It does appear that you need to explicitly instantiate the object once, then you can access its methods anywhere without specifically referring to that instance.

Some reports I've seen suggest that this is only the case for an in-proc server, that an out-of-proc one would work "automagically". I'm too lazy to test this myself.

Vi2

unread,
Oct 16, 2009, 6:02:34 AM10/16/09
to
On 14 окт, 00:20, "Igor Tandetnik" <itandet...@mvps.org> wrote:

> Yes, you seem to be right, [appobject] doesn't quite work the way I expected it to work. It does appear that you need to explicitly instantiate the object once, then you can access its methods anywhere without specifically referring to that instance.

[appobject] object works as you pointed earlier: "It basically


instructs VB to create an instance of the class automatically, and to
make it available under the library name."

' I variant
Private Sub Form_Load()
Dim o As RECLib.Cx
Set o = New RECLib.Cx

Debug.Print o.GetValue, RECLib.GetValue, GetValue ' => 222 222 222
End Sub

' II variant
Private Sub Form_Load()
Debug.Print RECLib.GetValue, GetValue ' => 222 222
End Sub

I suggest to look for TYPEFLAG_FAPPOBJECT in MSDN library for more
information.

Vi2

unread,
Oct 16, 2009, 6:17:10 AM10/16/09
to
On 16 окт, 15:02, Vi2 <sharac...@hotmail.com> wrote:

I forgot C++ description of GetValue

STDMETHODIMP Cx::GetValue(/*[out,retval]*/ long* val)
{
if (val) *val = 222;
return S_OK;
}

If I changed this function on:

STDMETHODIMP Cx::GetValue(/*[out,retval]*/ long* val)
{
if (val) *val = (int) this;
return S_OK;
}

that output looks like this:

10225664 10225720 10225720 for I variant
10225664 10225664 for II variant

So that, o.GetValue and RECLib.GetValue are called on distinct
objects.

0 new messages