Creating a basic COM object
-
I am trying to make a basic COM object for some .Net code to call, and it isn't working out too well. I have done a LOT of ATL COM development, so I understand COM pretty well. When referencing the COM object, VS2008 is seeing the interface correctly and is able to create the object. When the method is called (either via the interface or via reflection), it errors out with:
Member not found. (Exception from HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND))
So here is the code:
SalesCenterHttpClient.h
@#include <QObject>
#include <QNetworkAccessManager>
#include <QUrl>QT_BEGIN_NAMESPACE
class QSslError;
class QAuthenticator;
class QNetworkReply;
QT_END_NAMESPACEclass SalesCenterHttpClient : public QObject
{
Q_OBJECTpublic:
explicit SalesCenterHttpClient(QObject *parent = 0);Q_INVOKABLE void downloadContent( const QString& urlText );
void downloadContent( const QUrl& urlText );
Q_INVOKABLE int waitForDownloadContent( const QString& urlText );
int waitForDownloadContent( const QUrl& urlText );
Q_INVOKABLE QString errorMessage() const;
Q_INVOKABLE int error() const;
Q_INVOKABLE const QByteArray& content() const;
Q_INVOKABLE void clear();private slots:
void cancelDownload();
void httpFinished();
void httpReadyRead();
void updateDataReadProgress(qint64 bytesRead, qint64 totalBytes);
void slotAuthenticationRequired(QNetworkReply*,QAuthenticator );
#ifndef QT_NO_OPENSSL
void sslErrors(QNetworkReply,const QList<QSslError> &errors);
#endifsignals:
void readBytes(qint64 bytesRead, qint64 totalBytes);
void finished();private:
QUrl _url;
QNetworkAccessManager _qnam;
QNetworkReply *_reply;
QByteArray _data;
int _httpGetId;
bool _httpRequestAborted;
bool _ready;
QString _errorMsg;
int _errorCode;
int _httpStatusCode;void startRequest(QUrl url);
void setError( const QString& msg, int code );
};@The cpp file will be in the first reply...
-
SalesCenterHttpClient.cpp
@#include <QtNetwork>
#include <ActiveQt/QAxFactory>QAXFACTORY_DEFAULT(SalesCenterHttpClient,
"{88A5EF8E-A926-4eca-AE9C-9AAEBA7C1ACD}",
"{06EC5DCF-EE32-4ce8-9F84-A717440C45E7}",
"{478050B5-1787-4997-ADF2-F12B4BFB828D}",
"{EA660B4F-505E-4d70-8356-D56814B8F5B3}",
"{F3E80B9F-3512-4c64-BA77-69881CEAD399}")SalesCenterHttpClient::SalesCenterHttpClient(QObject *parent) : QObject(parent)
{
_httpRequestAborted = false;
_ready = true;connect(&_qnam, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
this, SLOT(slotAuthenticationRequired(QNetworkReply*,QAuthenticator*)));
#ifndef QT_NO_OPENSSL
connect(&_qnam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
this, SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
#endif
_errorCode = 0;
}void SalesCenterHttpClient::clear()
{
_data.clear();
_httpRequestAborted = true;
_ready = true;
}void SalesCenterHttpClient::startRequest(QUrl url)
{
setError("",0);
_reply = _qnam.get(QNetworkRequest( _url));
connect(_reply, SIGNAL(finished()), this, SLOT(httpFinished()));
connect(_reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead()));
connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDataReadProgress(qint64,qint64)));
}void SalesCenterHttpClient::downloadContent( const QString& urlText )
{
downloadContent( QUrl(urlText));
}void SalesCenterHttpClient::downloadContent( const QUrl& urlText )
{
if (!_ready)
cancelDownload();
_data.clear();
_url = urlText;
// schedule the request
_httpRequestAborted = false;
_ready = false;
startRequest(_url);
}/*! Start download with wait event loop until the download is completed. */
int SalesCenterHttpClient::waitForDownloadContent( const QString& urlText )
{
return waitForDownloadContent( QUrl(urlText));
}int SalesCenterHttpClient::waitForDownloadContent( const QUrl& urlText )
{
_httpStatusCode = 0;downloadContent(urlText);
while(!_ready)
QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);return _httpStatusCode;
}void SalesCenterHttpClient::cancelDownload()
{
setError( tr("Download canceled."), -2 );
_httpRequestAborted = true;
_ready = true;
_reply->abort();
}void SalesCenterHttpClient::httpFinished()
{
if (_httpRequestAborted) {
_data.clear();
_reply->deleteLater();
return;
}_httpStatusCode = _reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QVariant redirectionTarget = _reply->attribute(QNetworkRequest::RedirectionTargetAttribute);qDebug() << redirectionTarget;
if (_reply->error())
{
_data.clear();
setError( tr("Download failed: %1.").arg(_reply->errorString()), -1 );
}
else if (redirectionTarget.isValid())
{
QUrl newUrl = _url.resolved(redirectionTarget.toUrl());
qDebug() << newUrl;
if (newUrl != _url)
{
// handle redirection
_url = newUrl;
_reply->deleteLater();
_data.clear();
startRequest(_url);
return;
}
}
else
{
}_reply->deleteLater();
_reply = 0;
_ready = true;
emit finished();
}void SalesCenterHttpClient::setError(const QString &msg, int code)
{
_errorMsg = msg;
_errorCode = code;
}void SalesCenterHttpClient::httpReadyRead()
{
// this slot gets called everytime the QNetworkReply has new data.
// We read all of its new data and write it into the file.
// That way we use less RAM than when reading it at the finished()
// signal of the QNetworkReply
_data.append(_reply->readAll());
}void SalesCenterHttpClient::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
if (_httpRequestAborted)
return;
emit readBytes( bytesRead, totalBytes);
}void SalesCenterHttpClient::slotAuthenticationRequired( QNetworkReply*, QAuthenticator *auth)
{
//setError( tr("Authentication required: %1 at %2").arg(authenticator->realm()).arg(url.host()), -3 );
auth->setUser("<username>");
auth->setPassword("<password>");
}QString SalesCenterHttpClient::errorMessage() const
{
return _errorMsg;
}int SalesCenterHttpClient::error() const
{
return _errorCode;
}#ifndef QT_NO_OPENSSL
void SalesCenterHttpClient::sslErrors(QNetworkReply*,const QList<QSslError> &errors)
{
QString errorString;
foreach (const QSslError &error, errors) {
if (!errorString.isEmpty())
errorString += ", ";
errorString += error.errorString();
}
setError( tr("One or more SSL errors has occurred: %1").arg(errorString), -4 );
}
#endifconst QByteArray& SalesCenterHttpClient::content() const
{
return _data;
}@