PDA

View Full Version : Using Qt instead of lt_dlsym (libtool)



giorgik
20th April 2013, 18:03
Hello everybody, I'm running a ported from Linux to Windows using Qt 4.8.2. I am in a dead end. I do not know how to make the conversion from libtool to Qt. The following is a piece of code under test:


lt_dlhandle handle = NULL;

// the library name is the first word in the string
char libname[256];
sscanf( lib, "%s %*s", libname );

if(( handle = lt_dlopenext( libname ) ))
{
//printf( "]" );

model_callback_t initfunc = (model_callback_t)lt_dlsym( handle, "Init" );
if( initfunc == NULL )
{
printf( "Model::LoadControllerModule() - (Libtool error: %s.) Something is wrong" \
"with your plugin.\n", lt_dlerror() ); // report the error from libtool
puts( "libtool error #1" );
fflush( stdout );
exit(-1);
}

AddCallback( CB_INIT, initfunc, new CtrlArgs(lib, World::ctrlargs) ); // pass complete string into initfunc
}

The functions involved in the exchange are: lt_dlhandle, lt_dlopenext (), lt_dlsym ().
I have created the library wander.a (static) using Qt Creator 2.5.2, where there is the function Init (). The function Init () is the one that I use in the rest of the code after the second after loading the code above I would like to convert to Qt. The variable lib contains the name of the static library wander.
As regards the function AddCallback () has the following code (it is not to touch as they are already in place in Qt):


void Model::AddCallback( callback_type_t type, model_callback_t cb, void *user )
{
//callbacks[address].insert( cb_t( cb, user ));
callbacks[type].insert( cb_t( cb, user ));

// debug info - record the global number of registered callbacks
if( type == CB_UPDATE )
{
assert( world->update_cb_count >= 0 );
world->update_cb_count++;
}
}

Can you help me? I do not know how to do this part of code.

Santosh Reddy
20th April 2013, 18:33
You can use QLibrary, there are couple of ways to do this, here is an example. Make sure you read the basics of how to use QLibrary

char libname[] = "library1 library2";
QString lib = QString(libname).split(" ").at(0);

QLibrary library(lib);
model_callback_t initfunc = (model_callback_t)library.resolve("Init");

if(initfunc == 0)
{
qDebug() << "Model::LoadControllerModule() - (Libtool error: " << library.errorString() << ")"
"Something is wrong with your plugin."; // report the error from QLibrary
qDebug() << "QLibrary error #1";
qApp->exit(-1);
}

AddCallback(CB_INIT, initfunc, new CtrlArgs(lib, World::ctrlargs)); // pass complete string into initfunc

giorgik
20th April 2013, 19:18
Thanks Santosh Reddy, I try now your solution. I am very grateful.
I tried using your solution. Your piece of code is OK, the problem now is my static library libwander.a
I get this response by running the code with your part:


Model::LoadControllerModule() - [Ctrl "wander"
Model::LoadControllerModule() - (Libtool error: "Cannot load library wander: Impossibile trovare il modulo specificato." ) Some thing is wrong with your plugin.
QLibrary error #1

Carry a piece of code of my static library named libwander.a.


extern "C" int Init( Model *mod, CtrlArgs *args )
{
// local arguments
/* printf( "\nWander controller initialised with:\n"
"\tworldfile string \"%s\"\n"
"\tcmdline string \"%s\"",
args->worldfile.c_str(),
args->cmdline.c_str() );
*/

robot_t *robot = new robot_t;

robot->avoidcount = 0;
robot->randcount = 0;

robot->pos = (ModelPosition *)mod;

if( verbose )
robot->pos->AddCallback( Model::CB_UPDATE, (model_callback_t)PositionUpdate, robot );

robot->pos->Subscribe(); // starts the position updates

robot->laser = (ModelRanger *)mod->GetChild( "ranger:1" );
robot->laser->AddCallback( Model::CB_UPDATE, (model_callback_t)LaserUpdate, robot );
robot->laser->Subscribe(); // starts the ranger updates

return 0; //ok
}

The static library libwander.a was created in Qt. I report the project file:


QT += opengl

TARGET = wanderd
TEMPLATE = lib
CONFIG += staticlib

INCLUDEPATH += C:/Qt/progetti/Simulatore

SOURCES += wander.cpp

HEADERS += \
wander.h

The part of the code with your addition, it would now be:


void Model::LoadControllerModule( const char *lib )
{
printf( "Model::LoadControllerModule() - [Ctrl \"%s\"", lib );
fflush(stdout);

char libname[20];
strcpy(libname, lib);
QString libn = QString(libname).split(" ").at(0);
QLibrary library(libn);
model_callback_t initfunc = (model_callback_t)library.resolve("Init");
printf( "]" );

if(initfunc == 0)
{
qDebug() << "\nModel::LoadControllerModule() - (Libtool error: " << library.errorString() << ")"
"\nSomething is wrong with your plugin."; // report the error from QLibrary
qDebug() << "QLibrary error #1";
return;
}

AddCallback(CB_INIT, initfunc, new CtrlArgs(lib, World::ctrlargs)); // pass complete string into initfunc
}

Where did I go wrong ?

giorgik
20th April 2013, 21:54
A part of my error is due to the fact that the library to be created should be shared, not static.
But now I have another problem, I can not compile it as a shared library in Qt, as it tells me I can not find any references to the calling program (ie the one with your piece of code).
I can not solve this problem. The strange thing is that Qt Creator (in the project shared library) sees references to the project where there is your code ... and then how to solve this thing ? :confused:
Below I put the project file of the shared library:


QT += opengl

TARGET = wander
TEMPLATE = lib
CONFIG += dll

DEFINES += WANDER_LIBRARY

SOURCES += wander.cpp

HEADERS += wander.h\
wander_global.h

file wander.h:


#include "wander_global.h"
#include "C:/Qt/progetti/Simulatore/simulator.h"

namespace Sim
{

class Model;

WANDERSHARED_EXPORT int Init( Model *mod, CtrlArgs *args );
int LaserUpdate( Model *mod, robot_t *robot );
int PositionUpdate( Model *mod, robot_t *robot );

}

file wander.cpp:


#include "wander.h"


static const double cruisespeed = 0.4;
static const double avoidspeed = 0.05;
static const double avoidturn = 0.5;
static const double minfrontdistance = 1.0; // 0.6
static const bool verbose = false;
static const double stopdist = 0.3;
static const int avoidduration = 10;


using namespace Sim;


// Simulator calls this when the model starts up
extern "C" int Init( Model *mod, CtrlArgs *args )
{
// local arguments
/* printf( "\nWander controller initialised with:\n"
"\tworldfile string \"%s\"\n"
"\tcmdline string \"%s\"",
args->worldfile.c_str(),
args->cmdline.c_str() );
*/

robot_t *robot = new robot_t;

robot->avoidcount = 0;
robot->randcount = 0;

robot->pos = (ModelPosition *)mod;

if( verbose )
robot->pos->AddCallback( Model::CB_UPDATE, (model_callback_t)PositionUpdate, robot );

robot->pos->Subscribe(); // starts the position updates

robot->laser = (ModelRanger *)mod->GetChild( "ranger:1" );
robot->laser->AddCallback( Model::CB_UPDATE, (model_callback_t)LaserUpdate, robot );
robot->laser->Subscribe(); // starts the ranger updates

return 0; //ok
}

// inspect the ranger data and decide what to do
int LaserUpdate( Model *mod, robot_t *robot )
{
// get the data
const std::vector<meters_t> &scan = robot->laser->GetSensors()[0].ranges;
uint32_t sample_count = scan.size();
if( sample_count < 1 )
return 0;

bool obstruction = false;
bool stop = false;

// find the closest distance to the left and right and check if
// there's anything in front
double minleft = 1e6;
double minright = 1e6;

for (uint32_t i = 0; i < sample_count; i++)
{
if( verbose ) printf( "%.3f ", scan[i] );

if( (i > (sample_count / 3)) && (i < (sample_count - (sample_count / 3)))
&& scan[i] < minfrontdistance)
{
if( verbose ) puts( " obstruction!" );
obstruction = true;
}

if( scan[i] < stopdist )
{
if( verbose ) puts( " stopping!" );
stop = true;
}

if( i > sample_count / 2 )
minleft = std::min( minleft, scan[i] );
else
minright = std::min( minright, scan[i] );
}

if( verbose )
{
puts( "" );
printf( "minleft %.3f \n", minleft );
printf( "minright %.3f\n ", minright );
}

if( obstruction || stop || (robot->avoidcount>0) )
{
if( verbose ) printf( "Avoid %d\n", robot->avoidcount );

robot->pos->SetXSpeed( stop ? 0.0 : avoidspeed );

// once we start avoiding, select a turn direction and stick with it for a few iterations
if( robot->avoidcount < 1 )
{
if( verbose ) puts( "Avoid START" );
robot->avoidcount = random() % avoidduration + avoidduration;

if( minleft < minright )
{
robot->pos->SetTurnSpeed( -avoidturn );
if( verbose ) printf( "turning right %.2f\n", -avoidturn );
}
else
{
robot->pos->SetTurnSpeed( +avoidturn );
if( verbose ) printf( "turning left %2f\n", +avoidturn );
}
}

robot->avoidcount--;
}
else
{
if( verbose ) puts( "Cruise" );

robot->avoidcount = 0;
robot->pos->SetXSpeed( cruisespeed );
robot->pos->SetTurnSpeed( 0 );
}

// if( robot->pos->Stalled() )
// {
// robot->pos->SetSpeed( 0,0,0 );
// robot->pos->SetTurnSpeed( 0 );
// }

return 0; // run again
}

int PositionUpdate( Model *mod, robot_t *robot )
{
Pose pose = robot->pos->GetPose();

printf( "Pose: [%.2f %.2f %.2f %.2f]\n", pose.x, pose.y, pose.z, pose.a );

return 0; // run again
}

giorgik
21st April 2013, 18:15
Ok solved, it was just add all the object modules *.o the calling program

wysota
21st April 2013, 18:34
Ok solved, it was just add all the object modules *.o the calling program

If you mean what I think you do then you have effectively compiled your library into your main program which means that you're not using the library at all since all the code is already in your main app.