I´m trying to add a signal to my qthread, but I get an some errors:
error: undefined reference to `vtable for RFDongleCommunication'
error: undefined reference to `RFDongleCommunication::newLogger(unsigned char, unsigned char)'
This is my header file:
#ifndef RFDONGLECOMMUNICATION_H
#define RFDONGLECOMMUNICATION_H
#include <QThread>
#include "qextserialport.h"
#include <QtGui>
class RFDongleCommunication: public QThread
{
Q_OBJECT
public:
explicit RFDongleCommunication(QextSerialPort * port);
QextSerialPort * rfport;
QByteArray data;
signals:
void newLogger(uchar,uchar);
private:
void run();
};
#endif // RFDONGLECOMMUNICATION_H
And the cpp file
#include "rfdonglecommunication.h"
#include "QDebug"
RFDongleCommunication::RFDongleCommunication(QextSerialPort * port)
{
rfport=port;
}
void RFDongleCommunication::run()
{
while(!(rfport->bytesAvailable()));
data = rfport->readAll();
uchar id = data[1];
uchar type = data[2];
emit newLogger(id,type);
}
Does anybody see what I´m doing wrong?
Make shure your class is in a different .cpp and .h file that are included in the MOC process generation
Click on: File - New File or Project - Files and classes - C++ - New
class
undefined reference to `vtable means that the moc cpp file is not generated.
I see that this is a very old post, but it seems people still keep asking very similar or even exactly the same question. I would elaborate the answer given by Rudolfs Bundulis above a little, and hope it would be helpful.
In case you are using Qt Creator and when you compiled your project for the first time, you did not put "Q_OBJECT" in your header file, then the moc cpp file for your (qthread) cpp file was not generated. In this case, simply running "Clean All" and "Rebuild All" after putting "Q_OBJECT" in your header file will not work. You need to go to your build folder to manually delete the Qt generated "Makefile" and run "Rebuild All" or "Build All" again, your error message will be gone.
Related
I have a c++ webassembly module with several function that is called wasmExec.wasm. So far i have been exporting methods from c++ to JavaScript that are located in the cpp file where the main() method is located using the EMSCRIPTEN_KEEPALIVE keyword. That is working just fine. I do see those methods when i do
wasm-nm wasmExec.wasm
and i can call them from JavaScript and get the expected result. In order achieve clean methods name i have been disabling C++ name mangling.
Now i have tried to use EMSCRIPTEN_KEEPALIVE with static methods that are not located in the main.cpp file instead in a separate namespace and separate cpp and header files. In those classes i am also using EMSCRIPTEN_KEEPALIVE but unfortunately the produced wasm module is eliminating my method and thus i can not see them when executing wasm-nm wasmExec.wasm althout they are marked with EMSCRIPTEN_KEEPALIVE in the header as well as in the cpp file. i.e. here is an example
#ifndef API_REGISTRATION_REGISTRATIONMANAGER_H_
#define API_REGISTRATION_REGISTRATIONMANAGER_H_
#include <string>
#include <emscripten/emscripten.h>
using namespace std;
namespace api::registration {
#ifdef __cplusplus
extern "C" {
#endif
class RegistrationManager {
public:
explicit RegistrationManager();
virtual ~RegistrationManager();
static char* EMSCRIPTEN_KEEPALIVE registerClient(
char* userNameInputPtr, int userNameLength
);
};
#ifdef __cplusplus
}
#endif
}
#endif /* API_REGISTRATION_REGISTRATIONMANAGER_H_ */
I am using cmake to compile the project. In the target properties i have explicitly defined EXPORTED_FUNCTIONS to be equal to
set_target_properties(wasmExec PROPERTIES LINK_FLAGS "-std=c++17 -s WASM=1 -s TOTAL_MEMORY=512MB -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=1 -s VERBOSE=1 --pre-js /Projects/src/wasm/preModule.js -s DEMANGLE_SUPPORT=1 -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s EXPORTED_FUNCTIONS='['registerClient']' -s EXTRA_EXPORTED_RUNTIME_METHODS='['cwrap', 'getValue', 'setValue', 'registerClient' ]' " )
What could be the reason to not be able to register this the method "registerClient" within the webassembly module. I have even tired to use the option -s EXPORT_ALL=1 but that did not exported all the know methods as i was expcting it to do
I am compiling everything statically here i.e. below is the example of the registration_api cmake sub-folder
MESSAGE( STATUS "ADDING API_REGISTRATION_DIR")
set( API_REGISTRATION_SRC
RegistrationManager.h RegistrationManager.cpp
)
set(LIB_TYPE STATIC)
add_library(api_registration ${LIB_TYPE} ${API_REGISTRATION_SRC} )
target_include_directories(api_registration PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/")
the compilation process is successful with emscripten, nevertheless i do get this warrning exactly about the method i am trying to export:
em++: warning: undefined exported function: "registerClient" [-Wundefined]
if i put that method in the main.cpp it is automatically exported without any problem.
My question is what could be the reason why this export is not working when the method is located in external cp/hpp file?
Addition 15 May 2020: I was able to register the method only if i remove the class definition, change the namesapce to the one that main have. Then it seems that the underscore in the EXPORTED_FUNCTIONS is important i.e. -s EXPORTED_FUNCTIONS='['_registerClient']' . That worked for me. I was under the impression that if i use static methods that should work with classes as well, but it seems that not to be the case.
#ifndef API_REGISTRATION_REGISTRATIONMANAGER_H_
#define API_REGISTRATION_REGISTRATIONMANAGER_H_
#include <string>
#include <emscripten/emscripten.h>
using namespace std;
namespace wasm {
#ifdef __cplusplus
extern "C" {
#endif
char* EMSCRIPTEN_KEEPALIVE registerClient(
char* userNameInputPtr, int userNameLength
);
#ifdef __cplusplus
}
#endif
}
#endif /* API_REGISTRATION_REGISTRATIONMANAGER_H_ */
thus my question has changed to: Can emscripten register a static method of a class with EMSCRIPTEN_KEEPALIVE or not?
I am trying to make a threaded grabber for my OpenCV application. I am unable to figure out why this code doesn't compile. It gives me an error that I believe means that the function call is wrong. However, it is the exact same way how I start a thread using std::thread usually! I want to use std::thread to accomplish it because it will offer more platform-independent compatibility, so please don't tell me to use a platform-specific library. I also want this to be STL-based, so no Boost or DLib. In my main.cpp, I have a working thread application, the code below:
#include <iostream>
#include <fstream>
#include <string>
#include <thread>
#include <mutex>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#define read_failure_threshold 512
long grabbers_active = 0;
namespace dev
{
class grabber
{
private:
bool enabled = false;
std::mutex lock;
int capture_mode;
int capture_id;
unsigned long read_failures = 0;
std::string stream;
std::string grabber_name;
cv::Mat image;
public:
void grabber_t()
{
.......[unimportant code]........
}
grabber(std::string name, int captureMode, int captureId, std::string location)
{
.......[unimportant code]........
}
void start()
{
if(!enabled)
{
std::thread grabber_thread(grabber_t);
grabber_thread.detach();
}
enabled = true;
grabbers_active++;
}
cv::Mat getImage()
{
.......[unimportant code]........
}
};
}
[ERRORS:]
In file included from /media/storage/programming/yash101/repos/Other/STL+OpenCV/threaded_grabber_template/main.cpp:1:0:
/media/storage/programming/yash101/repos/Other/STL+OpenCV/threaded_grabber_template/template.hpp: In member function ‘void dev::grabber::start()’:
/media/storage/programming/yash101/repos/Other/STL+OpenCV/threaded_grabber_template/template.hpp:119:52: error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>)’
std::thread grabber_thread(grabber_t);
^
/media/storage/programming/yash101/repos/Other/STL+OpenCV/threaded_grabber_template/template.hpp:119:52: note: candidates are:
In file included from /media/storage/programming/yash101/repos/Other/STL+OpenCV/threaded_grabber_template/template.hpp:4:0,
from /media/storage/programming/yash101/repos/Other/STL+OpenCV/threaded_grabber_template/main.cpp:1:
/usr/include/c++/4.8/thread:133:7: note: std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (dev::grabber::*)(); _Args = {}]
thread(_Callable&& __f, _Args&&... __args)
^
/usr/include/c++/4.8/thread:133:7: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘void (dev::grabber::*&&)()’
/usr/include/c++/4.8/thread:128:5: note: std::thread::thread(std::thread&&)
thread(thread&& __t) noexcept
^
/usr/include/c++/4.8/thread:128:5: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘std::thread&&’
/usr/include/c++/4.8/thread:122:5: note: std::thread::thread()
thread() noexcept = default;
^
/usr/include/c++/4.8/thread:122:5: note: candidate expects 0 arguments, 1 provided
make[2]: *** [CMakeFiles/build.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/build.dir/all] Error 2
make: *** [all] Error 2
The error log is also at the end of the code. The only errors I am worried about are the threading ones. The other ones are simple fixes, but require me to have the threading working.
I am in Ubuntu, using g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2. I have C++0x enabled in my CMakeLists.txt. Everything works perfectly in there
My main objective is to figure out why I am getting this error. I have been googling and trying different tricks for many hours, but nothing is working!
Thanks in advanced for your help :)
Change that :
std::thread grabber_thread(grabber_t);
Into that :
std::thread grabber_thread(&grabber::grabber_t, this);
grabber_t is a reference to non-static member function, you need to pass its address, but &grabber_t can't work as you must explicitly qualify name of member function when taking its address, thus resulting in &grabber::grabber_t.
so somewhere along the lines of putting this app together I've started to get a runtime check failure stack corruption when the destructor for a cstring class member is called.
I've gotten to the point of trying to debug this by throwing bricks at the issue but still havent root caused it. At the current moment the class that the cstring resides in does nothing but initialize its private string members and set a pointer to another class to NULL.
Interestingly if I do not set the class pointer to NULL and comment out that line the corruption goes away. I think this is somewhat of a red herring, and that something is changing in the way the compiler is putting the code together when it pulls in the .h file that contains theCLog definitions and that would be used since I'm declaring a pointer to that object.
int _tmain(int argc, _TCHAR* argv[])
{
DWORD a = 0xBABA; //just to help catch the corrupter
DWORD b = 0xDFDF;
CStringW startat = L"\\\\anetworkshare\\fre";
CStringW lookfor = L".inf";
DirEnum myEnum(startat,lookfor);
ULONG en = a + b;
en = a - b;
return 0;
}
DirEnum.cpp
DirEnum::DirEnum(CString startingdir,CString fileFilter)
{
m_plogfile = NULL; //If you comment out this line corruption goes away
m_startingdir = L"";
m_extfilter = L"";
if(startingdir.GetLength() > 0)
m_startingdir = startingdir;
if(fileFilter.GetLength() > 0)
m_extfilter = fileFilter;
//following commented out to tshoot
//CLogBase& ref = ref.GetInstance();
//logBase = &ref;
//m_plogfile = new CLog(L"DirEnumerator",L"logfile.txt",logINFO);
}
Now I suspect that something in the log.h file is causing a change to occuur in the ATL or CString libraries but I dont know what. Heres the log.h file
#pragma once
//#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
using namespace std;
#ifndef TYPEDEF_H
#define TYPEDEF_H
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <tchar.h>
#include <time.h>
//simple defines to allow the TCHAR library to be used
typedef std::basic_string<TCHAR> tstring;
typedef std::basic_ostream<TCHAR> tostream;
typedef std::basic_istream<TCHAR> tistream;
typedef std::basic_ostringstream<TCHAR> tostringstream;
typedef std::basic_istringstream<TCHAR> tistringstream;
typedef std::basic_ofstream<TCHAR> tofstream;
#if defined(UNICODE) || defined(_UNICODE)
#define tcout std::wcout
#define tcin std::wcin
#else
#define tcout std::cout
#define tcin std::cin;
#endif
#endif
#if defined DEBUG || defined (_DEBUG)
#define TOCONSOLE
#endif
typedef enum LOGLVL{logERROR =0,logWARN,logINFO,logDEBUG};
//CLogBase os a singleton log class. Intent is that you can establish a reference from anywhere in the project and write to the same file
// without having locking issues or threading issues
class CLogBase
{
public:
static CLogBase& GetInstance(CString logname = L"log.txt",LOGLVL lvl = logWARN);
~CLogBase(void);
tostringstream& GetLog(LOGLVL level);
tostringstream& GetStream(LOGLVL);
void Forceflush();
private:
CLogBase(CString file,LOGLVL lvl);
//our outstream
tostringstream m_os;
tostringstream m_dummy;
tofstream m_filestream;
CString m_filename;
LOGLVL m_reportlvl;
//Private declarations to prevent copy constructors from being invoked; these are do nothig implimentations
CLogBase(CLogBase const&);
void operator=(CLogBase const&);
};
class CLog
{
public:
CLog(CString component);
CLog(CString component,CString logname,LOGLVL lvl);
~CLog();
void Log(LOGLVL,CString message);
void CLog::Flush();
tostringstream& CLog::GetStream(LOGLVL lvl);
private:
CString m_componentname;
CLogBase* m_logBase;
};
I thought I would answer this as I found the issue. this was not a coding problem per se but a visual studio issue.
What happened was that I was storing the direnum.h file and .cpp file in a different directory than the one used for the main project. referencing the header with #include "..\somedir\direnum.h"
at one point in time visual studio reported the file as locked and did I want to overwrite \ cancel etc. I choose overwrite but what seemed to happen was that this caused VS to COPY the files to the current project. All my troubleshooting attempts were being edited in the local somename.h file whtne opened in the editor but the compiler was doing the correct thing and pulling down the .h file from the location above.
removing switching to the now local copy of direnum.h and recompiling fixed this as it was compiling part of the code as ANSI and the other part as WCHAR
I have a problem lunching a thread within a class A for example where the class A is a static member of class B with in a dll. I am using Visual Studio 9 and boost 1.40. Please consider the following code:
mylib.h:
#include <boost/thread.hpp>
#include <windows.h>
#ifdef FOO_STATIC
#define FOO_API
#else
#ifdef FOO_EXPORT
#define FOO_API __declspec(dllexport)
#else
#define FOO_API __declspec(dllimport)
#endif
#endif
class FOO_API foo{
boost::thread* thrd;
public:
foo();
~foo();
void do_work();
};
class FOO_API bar{
static foo f;
public:
static foo& instance();
};
mylib.cpp:
#include "mylib.h"
foo::foo()
{
thrd = new boost::thread(boost::bind(&foo::do_work,this));
}
foo::~foo(){
thrd->join();
delete thrd;
}
void foo::do_work(){
printf("doing some works\n");
}
foo& bar::instance(){return f;}
foo bar::f;
in the executable application, I have:
main.cpp:
#include "mylib.h"
void main(){
bar::instance();
}
If I link mylib statically to the executable app, It prints out "doing some works", while if I link it dynamically (dll), it does nothing.
I really appreciate any help.
Your program could be exiting before the thread completes. You might try waiting after the bar::instance() call, or joining the thread in main. Something else to try would be to flush stdout after the printf call.
From the MSDN documentation:
If your DLL is linked with the C
run-time library (CRT), the entry
point provided by the CRT calls the
constructors and destructors for
global and static C++ objects.
Therefore, these restrictions (*) for
DllMain also apply to constructors and
destructors and any code that is
called from them.
(*) The restrictions include communicating with threads.
It's best to make the global variable a pointer, and construct and release the object in dedicated callback routines.
See also this helpful SO answer.
I ran into troubles trying to create a gnome-panel applet with gtkmm. I dealt with most of them, but I'm now kind of blocked.
Quick summary : I tried libpanelappletmm, but every program (even the examples supplied in the source code) segfaults when I try to add the applet in my panel.
So I now use the C library (libpanel-applet). First I looked for a way to wrap the PanelApplet Gobject in a gtkmm C++-object, for example a Gtk::EventBox (PanelApplet inherits from GtkEventBox). I tried to cast it, but Glibmm kept throwing a warning ("Failed to wrap object 'PanelApplet'").
So I created a class "Info", inheriting from Gtk::HBox. In my main.cpp file I declare an instance of it, get the underlying GTK object (gobj method), and use the GTK+ functions to add it into the PanelApplet.
Here's my main.cpp.
#include <iostream>
#include <gtkmm.h>
#include <panel-applet.h>
#include "Info.hpp"
static void manage_timeboxes(BonoboUIComponent *uic, void *applet, const char* data) {
std::cout << "manage" << std::endl;
}
static gboolean getApplet(PanelApplet *applet, const gchar *iid, gpointer data) {
/*
if(iid != "OAFIID:TimeboxingApplet")
return false;
*/
Glib::init();
Gtk::Widget* content = new Info();
gtk_container_add(GTK_CONTAINER(applet), content->gobj());
static const char menu_xml[] =
"<popup name=\"button3\">\n"
" <menuitem name=\"Manage\" "
" verb=\"manage_timeboxes\" "
" _label=\"_Gérer l'emploi du temps\"\n"
" pixtype=\"stock\" "
" pixname=\"gtk-properties\"/>\n"
"</popup>\n";
static const BonoboUIVerb linked_verbs[] = {
BONOBO_UI_VERB ("manage_timeboxes", manage_timeboxes),
BONOBO_UI_VERB_END
};
panel_applet_setup_menu(applet, menu_xml, linked_verbs, data);
gtk_widget_show_all(GTK_WIDGET(applet));
return true;
}
PANEL_APPLET_BONOBO_FACTORY (
"OAFIID:TimeboxingApplet_Factory",
PANEL_TYPE_APPLET,
"Timeboxing",
"0.0",
getApplet,
NULL)
It works fine if I add labels or buttons in my Info object.
But then I tried to add an icon.
My first try was adding a Gtk::Image as a property of Info.
Info.hpp
#ifndef TIMEBOXING_INFO_H
#define TIMEBOXING_INFO_H
#include <gtkmm/box.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
class Info : public Gtk::HBox {
public:
Info();
virtual ~Info(){};
protected:
Gtk::Image icon;
Gtk::Label info;
};
#endif
Info.cpp
#include "Info.hpp"
#include <gtkmm/image.h>
#include <gtkmm/label.h>
Info::Info() : icon("/home/bastien/programmation/timeboxing-applet/icons/clock-24.png"), info("<b>En cours</b>") {
info.set_use_markup();
pack_start(icon);
pack_start(info);
show_all_children();
}
When I try to add the applet, I get this error and the program aborts :
glibmm:ERROR:objectbase.cc:78:void Glib::ObjectBase::initialize(GObject*): assertion failed: (gobject_ == castitem)
I commented "Gtk::Image icon" from Info.hpp, and I modified my constructor like this :
Info::Info() : info("<b>En cours</b>") {
info.set_use_markup();
Gtk::Image icon("/home/bastien/programmation/timeboxing-applet/icons/clock-24.png");
pack_start(icon);
pack_start(info);
show_all_children();
}
I'm not getting the Glibmm error anymore, but the image isn't displayed. I tried with another file, with an icon from the stock, and even with a Gdk::Pixbuf.
Thank you in advance !
Well, strangely enough, it works if I create a pointer to Gtk::Image.
If anyone has an explanation, it would be great !
Edit : apparently, I had to call Gtk::Main::init_gtkmm_internals. My wrapping troubles went away. I can wrap PanelApplet too, but if I use the resulting Gtk::EventBox* it doesn't display anything.