I am using VS2019
Trying to call a thread in DLL. to run two executables simultaneously with detach
following threads worked when I Run a normal c++ program
I get error
Error C3867 'myClass::runexeone': non-standard syntax; use '&' to create a pointer to member myGateway C:\Users\user\Downloads\Demo\myGateway\myplugin.cpp 21
plugin header
#include <windows.h>
#include <iostream>
#include <thread>
#define MYPLUGIN_EXPORT __declspec(dllexport)
extern "C"
{
MYPLUGIN_EXPORT void WINAPI OnStart();
}
pluging.cpp
#include "plugin.h"
using namespace std;
class myClass
{
public:
myClass()
{
}
~myClass()
{
}
void onStart()
{
std::thread(runexeone).detach();
std::thread(runexetwo).detach();
}
void runexeone()
{
int exerunpne = system("cmd /C \"%MY_ROOT%\\bin\\Mytest.exe\" -ORBEndpoint iiop://localhost:12345 -d");
}
void runexetwo()
{
int exeruntwo = system("cmd /C \"%MY_ROOT%\\bin\\Mytest_2.exe\" -ORBEndpoint iiop://localhost:12345 -d");
}
};
myClass& getmyclass()
{
static myClass myclass;
return myclass;
}
MYPLUGIN_EXPORT void WINAPI OnStart()
{
getmyClass().onStart();
}
The problem is that runexeone is an unqualified name of a member function, and std::thread needs something executable. runexeone isn't. VC++ tries to guess from context what you mean, but the suggestion isn't enough. Even if you had written &myClass::runexeone, it still wouldn't have worked, because myClass::runexeone also needs a this pointer. You can fix the latter problem by making it static.
Compiler suggestions work best when there's just one problem.
As MSalters already mentioned, you provided the wrong data type for the functor for std::thread. If you cannot make the method static (which you can actually at least for the current state of your code, but to let this not be unstated here), you can do this
void onStart()
{
std::thread(std::bind(&myClass::runexeone, this)).detach();
}
But be careful about the lifetime/existence of your object/this!
Related
So I've got this interface class that I include, both in the dll and the client project
// InterfaceClass.h
#pragma once
class InterfaceClass
{
public:
virtual void Update() = 0;
};
This is the dll class that calls one of its own methods inside update
// DLLClassThatDoesSomething.cpp
#include "InterfaceClass.h"
#include <iostream>
#include <string>
class __declspec(dllexport) DLLClass : public InterfaceClass
{
public:
void Update()
{
std::cout << this->GetString();
}
std::string& GetString()
{
std::string thestring = "bruhmoment";
return thestring;
}
};
extern "C"
{
__declspec(dllexport) InterfaceClass* CreateInstance()
{
return new DLLClass();
}
}
And this is the "Client" project
// main.cpp
#include "InterfaceClass.h"
#include <Windows.h>
typedef InterfaceClass* (__cdecl *Class) ();
int main()
{
HINSTANCE dll = LoadLibrary(L"DLLClass.dll");
Class klass = (Class)GetProcAddress(dll, "CreateInstance");
InterfaceClass* IKlass = klass();
IKlass->Update();
FreeLibrary(dll);
return 0;
}
The moment I call IKlass->Update() I get an exception for Access Memory Violation because of the DLLClass calling its own method.
I haven't tried anything since I barely know how to load a DLL on runtime and I've used this nifty tutorial
How can I let it call the method and not get thrown an exception? I'm trying to let ppl that will create mods for my game create their own mods with their custom classes for bosses, mobs and etc. in DLLs.
EDIT:
Turns out it was a syntax mistake on my end. Instead of return new DLLClass;, it had to be return new DLLClass();. After fixing it, it works as intended.
You return a reference to a local variable thestring, and by the time you try to access it in
std::cout << this->GetString(), referenced data is already destroyed. In fact, it is destroyed right after the end of enclosing scope of compound statement where the variable was declared.
It may "appear" to work sometimes due to the stack not being overwritten yet, but eventually it will fail miserably like it did in your case. This triggers UB (undefined behavior).
This question already has answers here:
Start thread with member function
(5 answers)
Closed 3 years ago.
When I compile the code below I get the following error. help me...!
Errors:
Error C2276 '&': illegal operation on bound member function expression
Error C3867 'CCore::Run': non - standard syntax; use '&' to create a pointer to member
I'm not sure if the program gives me an error.
I want to run the "Run" function of the Core class.
Core.cpp file contains only the functions created by the compiler.
I'm learning English so I'm not good yet. So please understand that the whole code.
// main.cpp
#include "Core.h"
#include <thread>
int main()
{
// The conditions below have been success
if (CCore::GetInstance().Init())
{
// The code below fails to compile.
// Error C3867 'CCore::Run': non - standard syntax; use '&' to create a pointer to member
thread main_thread(CCore::GetInstance().Run);
// Error C2276 '&': illegal operation on bound member function expression
thread main_thread(&CCore::GetInstance().Run);
main_thread.join();
}
return 0;
}
// Core.h
#pragma once
#include "Singleton.h"
#include <iostream>
using namespace std;
class CCore : public Singleton<CCore>
{
public:
CCore();
~CCore();
bool Init();
void Run();
};
// Singleton.h
#pragma once
template<typename T>
class Singleton
{
protected:
Singleton()=default;
~Singleton()=default;
public:
static T& GetInstance()
{
static T instance;
return instance;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton) = delete;
};
The compiler tells you the problem: Run() isn't a free function. It's a method, i.e. a function bound to an instance of an object. You have several options, but generally you either let the compiler synthesize a runnable for you, or write a free function yourself:
Let the compiler do all the work: guess what, it can make singletons for you so how cool is that?!
std::thread main_thread([]{
static CCore myCore;
myCore.Run();
});
You want to access that core? Sure!
std::future<CCore*> coreWhenDone = std::async([]{
static CCore myCore;
myCore.Run();
return &myCore;
});
Better yet, the core would provide some result, so that instead of accessing it directly when it's done, you could get its result (e.g. an int or std::vector<double> or whatever that core is computing)/
Let the compiler do some of the work:
std::thread main_thread([]{ CCore::GetInstance().Run(); });
Split the work between yourself and the compiler:
std::thread main_thread(std::bind(&CCore::Run, &CCore::GetInstance()));
Do all the work yourself:
void runCoreRun() {
CCore::GetInstance().Run();
}
...
std::thread main_thread(&runCoreRun);
Here's my scenario:
main.cpp
#include <Windows.h>
#include <functional>
std::function<void()> OnPrepare;
int WINAPI WinMain(HINSTANCE inst, HINSTANCE preInst, TCHAR*, int) {
if (OnPrepare) {
OnPrepare();
}
return 0;
}
other.cpp
#define _AFXDLL
#include <afx.h> // TRACE
#include <functional>
extern std::function<void()> OnPrepare;
class Init {
public:
Init() {
OnPrepare = []() {
TRACE("hello, world!\n");
};
}
};
Init g_init;
This code does not work in a Win32 application, but works well in a Console application. I don't know why. Can anyone point out what's wrong with my code? If I can't do it like this, is there a better way?
EDIT:
OnPrepare is always null in a Win32 application, so no "hello, world" will appear.
The code for constructingg_init modifies OnPrepare. This is, of course, only legal if OnPrepare has already been constructed. But what if g_init is constructed before OnPrepare? Then you'll be modifying an object that hasn't been constructed yet and then later constructing an object you've already modified. Ouch. Doing real work in the constructors of static objects is never a good idea.
It's not clear what your outer problem is, but this code isn't a good way to solve it. An ugly workaround is to replace your global std::function with a global function that returns a reference to a function static std::function and use that. That ensures the object is constructed before being assigned to.
std::function<void()>& getOnPrepare()
{
static std::function<void()> OnPrepare;
return OnPrepare;
}
Then the constructor of Init can call getOnPrepare, ensuring that OnPrepare is constructed before it's assigned to:
Init() {
getOnPrepare() = []() {
TRACE("hello, world!\n");
};
I am trying to make functions repository. I have created four files:
Function.hpp, Function.cpp, FunctionsRepository.hpp, FunctionsRepository.cpp
I want to keep pointers to functions in vector of pointers.
//FunctionsRepository.hpp
#ifndef FUNCTIONSREPOSITORY_HPP
#define FUNCTIONSREPOSITORY_HPP
#include <vector>
using namespace std;
class FunctionsRepository {
private:
static vector<double *> pointerToFunctions;
public:
static void addFunction(double * wsk);
};
#endif
//FunctionRepository.cpp
#include "FunctionsRepository.hpp"
void FunctionsRepository::addFunction(double * wsk) {
pointerToFunctions.push_back(wsk);
}
//Functions.hpp
#ifndef FUNCTIONS_HPP
#define FUNCTOINS_HPP
#include "FunctionsRepository.hpp"
int constFunction(int numberOfVehicles);
void linearFunction();
void stepFunction();
#endif
//Funcctions.cpp
#include "Functions.hpp"
double constFunction(double numberOfVehicles){
return numberOfVehicles/2;
}
double (*funcConstant)(double) = constFunction;
//ERROR HERE
FunctionsRepository::addFunction(funcConstant);
I want to add new functions to program as easily as its possible and use it leater in other parts of program.
But I dont get it. Why i am getting this error. The addFunction() method is static, that means I can use it in other classes or parts of program. Vector is static to make sure that is the only one copy for whole program.
Use function wrapper. std::function can stores callable objects. So, your code will contain something like this:
class FunctionsRepository {
private:
// void() - function prototype
static std::vector<std::function<void()>> pointerToFunctions;
public:
static void addFunction(std::function<void()> wsk)
{
pointerToFunctions.push_back(wsk);
}
};
for more information consult official documentation: http://en.cppreference.com/w/cpp/utility/functional/function
I solved It. I received an error because I was calling the FunctionsRepository::addFunction(funcConstant); expression out of any scope. I just created new function to execute this command and thats all.
I'm racking my brain trying to find out how to write cross platform classes while avoiding the cost of virtual functions and any kind of ugliness in the platform specific versions of classes. Here is what I have tried.
PlatformIndependantClass.hpp
class PlatformIndependantClass {
public:
PlatformIndependantClass();
std::string GetPlatformName();
private:
PlatformIndependantClass* mImplementation;
};
LinuxClass.hpp
#include "PlatformIndependantClass.hpp"
class LinuxClass : public PlatformIndependantClass{
public:
std::string GetPlatformName();
};
WindowsClass.hpp
#include "PlatformIndependantClass.hpp"
class WindowsClass : public PlatformIndependantClass {
public:
std::string GetPlatformName();
};
PlatformIndependantClass.cpp
#include "PlatformIndependantClass.hpp"
#include "LinuxClass.hpp"
#include "WindowsClass.hpp"
PlatformIndependantClass::PlatformIndependantClass() {
#ifdef TARGET_LINUX
mImplementation = new LinuxClass();
#endif
#ifdef TARGET_WINDOWS
mImplementation = new WindowsClass();
#endif
}
std::string PlatformIndependantClass::GetPlatformName() {
return mImplementation->GetPlatformName();
}
LinuxClass.cpp
#include "LinuxClass.hpp"
std::string LinuxClass::GetPlatformName() {
return std::string("This was compiled on linux!");
}
WindowsClass.cpp
#include "WindowsClass.hpp"
std::string WindowsClass::GetPlatformName() {
return std::string("This was compiled on windows!");
}
main.cpp
#include <iostream>
#include "PlatformIndependantClass.hpp"
using namespace std;
int main()
{
PlatformIndependantClass* cl = new PlatformIndependantClass();
cout << "Hello world!" << endl;
cout << "Operating system name is: " << cl->GetPlatformName() << endl;
cout << "Bye!" << endl;
return 0;
}
Now, this compiles fine but I get a segmentation fault. I believe this is because the platform specific classes inherit from PlatformIndependantClass, which on construction, creates an instance of the platform specific class, so I get infinite recursion. Every time I try, I just get extremely confused!
How can I achieve a design like this properly? Or is this just a horrible idea. I have been trying to find out how to write cross platform classes but I just get a load of results about cross platform libraries, any help will be gratefully accepted :)
I think what you are trying to accomplish can be accomplished much easier...
Object.h:
#include <normal includes>
#if WINDOWS
#include <windows includes>
#endif
#if LINUX
#include <linux includes>
#endif
class Object
{
private:
#if WINDOWS
//Windows Specific Fields...
#endif
#if LINUX
//Linux Specific Fields...
#endif
public:
//Function that performs platform specific functionality
void DoPlatformSpecificStuff();
//Nothing platform specific here
void DoStuff();
};
Object.cpp
#include "Object.h"
void Object::DoStuff() { ... }
ObjectWin32.cpp
#if WINDOWS
#include "Object.h"
void Object::DoPlatformSpecificStuff()
{
//Windows specific stuff...
}
#endif
ObjectLinux.cpp
#if LINUX
#include "Object.h"
void Object::DoPlatformSpecificStuff()
{
//Linux specific stuff...
}
#endif
And so on. I think this could accomplish what you are trying in a bit easier fashion. Also, no virtual functions needed.
Starting from the end, yes, truly a horrible idea, as are most ideas that start with "I want to avoid the cost of virtual functions".
As to why you're getting the segmentation fault (stack overflow specifically), it's because you aren't using virtual functions, but static linking. The compiler doesn't know that mImplementation is anything but a PlatformIndependantClass, so when you try to call return mImplementation->GetPlatformName() you're calling the same function over and over.
What you achieved is called shadowing, you're using compile-time function resolution. The compiler will call the GetPlatformName function of the actual type of the variable you're calling it from, since there's no virtual table to overwrite the pointers to the actual functions. Since mImplementation is PlatformIndependantClass, mImplementation->GetPlatformName will always be PlatformIndependantClass::GetPlatformName.
Edit: Of course the question of why you need to create both a Windows and a Linux copy of your engine at the same time comes to mind. You'll never use both of them at the same time, right?
So why not just have two different libraries, one for each system, and link the right one from your makefile. You get the best of all worlds!
Instead of using the constructor to build the platform-specific instance, I would create a static factory method to create the instances:
PlatformIndependantClass* PlatformIndependantClass::getPlatformIndependantClass() {
#ifdef TARGET_LINUX
return new LinuxClass();
#endif
#ifdef TARGET_WINDOWS
return new WindowsClass();
#endif
}
This way you avoid the recursion, and you also don't need your mImplementation pointer.
I would also try to avoid platform-specific classes, but that's another story :)
When you want to have polymorphic behavior without any run-time overhead, you can try the curiously recurring template pattern (CRTP). The base class is a template, and the derived class uses itself as the template parameter for the base. This requires your classes to be defined as templates, which further restricts them to be implemented completely in the header (.hpp) files.
I'm not sure how to apply the pattern in your particular case.
I don't think the constructor is causing the infinite recursion. It's the GetPlatformName() function. Because it's not set as virtual, it can only call itself.
Two solutions: Make that function virtual, or do away with the inheritance completely.
Either way, the cost of a function only calling another function will be more expensive than using virtual functions in the first place. So I would say keep the inheritance, and virtualize the functions specific to the platform, and call them directly, without going through a base class function.
You are correct about the infinte loop. The fix is actually easier than you'd think.
PlatformIndependantClass.hpp
#include //portable headers
struct PlatformDependantClass; //defined in Cpp file
class PlatformIndependantClass {
public:
PlatformIndependantClass();
~PlatformIndependantClass();
std::string GetPlatformName();
private:
std::unique_ptr<PlatformDependantClass> mImplementation; //note, different type
};
LinuxClass.cpp
#ifdef __GNUC__
#include //linux headers
#include "PlatformIndependantClass.hpp"
struct PlatformDependantClass { //linux only stuff
//stuff
};
PlatformIndependantClass() {
mImplementation.reset(new PlatformDependantClass );
}
~PlatformIndependantClass() {
}
std::string PlatformIndependantClass::GetPlatformName() {
return std::string("This was compiled on linux!");
}
#endif //__GNUC__
WindowsClass.cpp
#ifdef _MSC_VER
#include //windows headers
#include "PlatformIndependantClass.hpp"
struct PlatformDependantClass { //windows only stuff
//stuff
};
PlatformIndependantClass() {
mImplementation.reset(new PlatformDependantClass );
}
~PlatformIndependantClass() {
}
std::string PlatformIndependantClass::GetPlatformName() {
return std::string("This was compiled on Windows!");
}
#endif //_MSC_VER
There's only ONE class defined here. In windows, it only compiles and contains windows stuff, and in Linux, it only compiles and contains linux stuff. Note that the void* thing is called an "Opaque pointer" or "pimpl idiom" http://en.wikipedia.org/wiki/Opaque_pointer