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.
--------------------
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
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
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;
}
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...
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.
> 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.
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.