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.
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've searched for the error LNK2005 "already defined in .obj" but can't find content related to the specific problem I am facing. Hope someone can help me on this...
I've a header foo.h
// foo.h
#ifndef FOO_H
#define FOO_H
void foo() {
print("foo\n");
}
#endif
and main file... main.cpp
// main.cpp
#include <thread>
#include "foo.h"
int main() {
std::thread t(foo);
t.join();
return 0;
}
Now, it compile without any errors and gives the gives output to the console...
foo
But if I create another file foo.cpp and just include the header foo.h and do nothing else...
// foo.cpp
#include "foo.h"
...I get linker error LNK2005 "void __cdecl foo(void)" (?foo##YAXXZ) already defined in main.obj
Don't know what's going wrong here.?!!
You must place only the prototype of the foo() function in the header file, and the implementation once in the .cpp.
Thus, foo.h must contain:
#pragma once
void foo();
And foo.cpp:
#include "foo.h"
void foo() {
printf("Whatever");
}
I'm using dlopen() and dlclose() to load and unload a module. The module contains some static data which needs to be destructed when dlclose() is called. However I'm finding that under certain circumstances dlclose() does not call the destructors - instead they are only called when main() exits.
I've boiled my code down to this. I have a class which contains a virtual function getType() defined inside the class, making reference to static data. I also have a StaticDestructionChecker object which just prints when the static constructors and destructors are being called. Finally I have a main() function that loads everything else via dlopen(), closes it via dlclose() and prints when main() is finished:
module1.h
#ifndef MODULE1_H
#define MODULE1_H
class MyClass
{
public:
MyClass();
virtual ~MyClass();
virtual int& getType() const
{
static int t(123);
return t;
}
};
#endif // MODULE1_H
module1.cpp
#include <stdio.h>
#include "module1.h"
MyClass::MyClass()
{
}
MyClass::~MyClass()
{
}
class StaticDestructionChecker
{
public:
StaticDestructionChecker()
{
printf("Constructing static data\n");
}
~StaticDestructionChecker()
{
printf("Destructing static data\n");
}
};
StaticDestructionChecker checker;
main:
#include <dlfcn.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
void* handle = dlopen("module1.so", RTLD_NOW);
if (!handle) printf("dlopen error: %s\n", dlerror());
dlclose(handle);
printf("end of main\n");
return 0;
}
Running all this as-is causes the static data to be destructed after main terminates, ie the output is:
Constructing static data
end of main
Destructing static data
The problem is with the virtual/static combo in getType(). If I change getType() to be non-virtual OR if I remove the "static int t", the destructors get called when expected, ie output is:
Constructing static data
Destructing static data
end of main
Is there a way to get the correct destruction order while still keeping the virtual/static code? FYI this is a simplified version of a sort of custom RTTI system, where getType() is automatically generated via a DECLARE_xxx macro, so I don't want to move the implementation into the cpp file because there would need to be a second macro call in there too.
I am using GCC 4.8 on Ubuntu 12.
Thanks
See dlclose() doesn't work with factory function & complex static in function?
If you use gold linker than passing --no-gnu-unique flag when linking module1.so fixes the problem:
]$ g++ -o module1.so -shared -fPIC -Wl,--no-gnu-unique module1.cpp
]$ g++ main.cpp -ldl
]$ LD_LIBRARY_PATH=. ./a.out
Constructing static data
Destructing static data
end of main
I don't know what are other consequences of using that flag.
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'm creating c++ game server. The server creates many objects monster, and every monster should have its thread with specific function.
I get error :
error C2064: term does not evaluate to a function taking 0 arguments
thread.hpp(60) : while compiling class template member function 'void
boost::detail::thread_data<F>::run(void)'
monster.cpp:
#include "monster.h"
monster::monster(string temp_mob_name)
{
//New login monster
mob_name = temp_mob_name;
x=rand() % 1000;
y=rand() % 1000;
boost::thread make_thread(&monster::mob_engine);
}
monster::~monster()
{
//Destructor
}
void monster::mob_engine()
{
while(true)
{
Sleep(100);
cout<< "Monster name"<<mob_name<<endl;
}
}
monster.h:
#ifndef _H_MONSTER_
#define _H_MONSTER_
//Additional include dependancies
#include <iostream>
#include <string>
#include "boost/thread.hpp"
using namespace std;
class monster
{
public:
//Functions
monster(string temp_mob_name);
~monster();
//Custom defined functions
void mob_engine();
int x;
int y;
};
//Include protection
#endif
mob_engine is a non-static member function, so it has an implicit this argument.
Try this:
boost::thread make_thread(boost::bind(&monster::mob_engine, this));
According to this similar question boost:thread - compiler error you can even avoid using bind by simply writing:
boost::thread make_thread(&monster::mob_engine, this);
Also, you will probably want to declare a boost::thread member variable to keep a reference to the thread.