PDA

View Full Version : Borland to Qt migration, Qt ActiveX COM automation of Borland Builder 6 App



Miss_Mc
18th December 2018, 15:10
I am tring to communicate with a CoClass "GDAS" over COM from a Qt App with imported code from a from Studio Rad (Embarcadro) project (using the borland compiler and environment). The CoClass I need to access is contained in a locally created Borland Builder 6 App "GeDetekt.exe" as "GeDetekt.tlb"

I succesfully generated a namespace and the type wrappers GeDetekt.h and GeDetekt.cpp as explained http://doc.qt.io/qt-5/activeqt-container.html

by including




TYPELIBS = "C:\Users\Jennifer McClellant\Documents\Development\Opus Rs Alpha\GeDetekt.exe"



in my .pro file.

With GeDetekt.h now included on the Qt side I can now create and initialize the server:




int ComClient::connectToServer()
{
STARTUPINFOA sicomServer;
PROCESS_INFORMATION picomServer;
memset(&picomServer, 0, sizeof(picomServer));
memset(&sicomServer, 0, sizeof(sicomServer));

sicomServer.dwFlags = STARTF_USESTDHANDLES;
sicomServer.cb = sizeof(STARTUPINFO);
sicomServer.lpReserved = nullptr;
sicomServer.lpDesktop = nullptr;
sicomServer.lpTitle = nullptr;
sicomServer.cbReserved2 = 0;
sicomServer.lpReserved2 = nullptr;
sicomServer.dwFlags = 0;

std::string path = getPathToServer();
std::replace(path.begin(), path.end(), '/', '\\');
LPSTR str = static_cast<LPSTR>(const_cast<char*>(path.c_str()));
int res = CreateProcessA(nullptr, str, nullptr, nullptr, false, 0,
nullptr, nullptr, &sicomServer, //(s)tartup (i)nformation
&picomServer);//(p)rocess (i)nformation, handle

if (res == 0)
{
QMessageBox msgBox;
msgBox.setText("Unable to start COM Server.");
msgBox.exec();
errorExit("GetProcessId");
}

for (int j = 0; j < 100; j++)//time to let COM server establish
{
Sleep(10);

if (!(j % 10))
{
QApplication::processEvents();
}
}

comServer = new GeDetekt::GDAS();
isServerActive = true;

dataRetrievalTimer->start(timerCount);
statusRetrievalTimer->start(timerCount);

return 1;
}

std::string ComClient::getPathToServer()
{
std::string path = QDir::currentPath().toStdString() + "\\System";
std::string iniFilePath = path + "\\" + "Sentinel.ini";

QSettings sentinelIni("Grandperspective", "Sentinel");

sentinelIni.setValue("GlobalSettings/OPUS_RS_PATH",
"C:/Users/Jennifer McClellant/Documents/Development/Opus Rs Alpha/GeDetekt.exe");

std::string name = sentinelIni.value("GlobalSettings/OPUS_RS_PATH").toString().toStdString();
std::string geDetektPath = name.empty()? std::string(): name;
return geDetektPath;
}



GeDetekt.exe starts, the server Api on client side (Qt side) seems to be initialised however when tring to run the methods e.g "ReturnStatus" on the server and access the returned data from the COM buffer, the QVariants are not valid (do not return data content).




void ComClient::getStatusFromServer()
{
if (!isServerActive)
{
return;
}

statusRetrievalTimer->stop();

QVariant status;
comServer->ReturnStatus(status);

VARIANT varStatus;
QVariantToVARIANT(status, varStatus);

//check type: (array | real 8 byte (double))
if (varStatus.vt == (VT_I1 | VT_ARRAY))
{
//--SafeArray: create with the VARIANT type
SAFEARRAY *safeArr = V_ARRAY(&varStatus);

//--SafeArray: dimensions (bounds information)
long lLbound = 0;
long lUbound = 0;
SafeArrayGetLBound(safeArr, 1, &lLbound);
SafeArrayGetUBound(safeArr, 1, &lUbound);
int amountStatusFlags = static_cast <int>(lUbound - lLbound + 1);

//--SafeArray: access the data
bool *actualData;
SafeArrayAccessData(safeArr, reinterpret_cast<void**>(&actualData));

serverStatus.clear();
for (int i = 0; i < amountStatusFlags; i++)
{
serverStatus.push_back(static_cast<bool>(actualData[i]));
}

SafeArrayUnaccessData(safeArr);
}
statusRetrievalTimer->start(timerCount);
}



What could I have overseen? Please someone help.