In my application I got many instances of class CDbaOciNotifier. They all share a pointer to only one instance of class OCIEnv.
What I like to achieve is that allocation and deallocation of the resource class OCIEnv will be handled automatically inside class CDbaOciNotifier.
The desired behaviour is, with the first instance of class CDbaOciNotifier the environment will be created, after that all following notifiers use that same environment. With the destruction of the last notifier, the environment will be destroyed too (call to custom deleter).
Later on, this cycle can start again with the creation of a new environment.
What I've got so far (using a static factory method to create notifiers):
#pragma once
#include <string>
#include <memory>
#include "boost\noncopyable.hpp"
class CDbaOciNotifier : private boost::noncopyable
{
public:
virtual ~CDbaOciNotifier(void);
static std::auto_ptr<CDbaOciNotifier> createNotifier(const std::string &tnsName, const std::string &user, const std::string &password);
private:
CDbaOciNotifier(OCIEnv* envhp);
// All notifiers share one environment
static OCIEnv* m_ENVHP;
// Custom deleter
static void freeEnvironment(OCIEnv *env);
OCIEnv* m_envhp;
};
CPP:
#include "DbaOciNotifier.h"
using namespace std;
OCIEnv* CDbaOciNotifier::m_ENVHP = 0;
CDbaOciNotifier::~CDbaOciNotifier(void)
{
}
CDbaOciNotifier::CDbaOciNotifier(OCIEnv* envhp)
:m_envhp(envhp)
{
}
void CDbaOciNotifier::freeEnvironment(OCIEnv *env)
{
OCIHandleFree((dvoid *) env, (ub4) OCI_HTYPE_ENV);
*env = null;
}
auto_ptr<CDbaOciNotifier> CDbaOciNotifier::createNotifier(const string &tnsName, const string &user, const string &password)
{
if(!m_ENVHP)
{
OCIEnvCreate( (OCIEnv **) &m_ENVHP, OCI_EVENTS|OCI_OBJECT, (dvoid *)0,
(dvoid * (*)(dvoid *, size_t)) 0,
(dvoid * (*)(dvoid *, dvoid *, size_t))0,
(void (*)(dvoid *, dvoid *)) 0,
(size_t) 0, (dvoid **) 0 );
}
//shared_ptr<OCIEnv> spEnvhp(m_ENVHP, freeEnvironment); ...got so far...
return auto_ptr<CDbaOciNotifier>(new CDbaOciNotifier(m_ENVHP));
}
I'd like to avoid counting references (notifiers) myself, and use something like shared_ptr.
Do you see an easy solution to my problem?
There is a lot going on in your code. Here is the solution, but simplified to just the bare essentials.
class CDbaOciNotifier
{
public:
CDbaOciNotifier() :
m_resource(get_env())
{ }
private:
shared_ptr<OCIEnv> m_env;
struct Delete_env
{
void operator()(OCIEnv* env)
{
OCIHandleFree( ... );
}
};
static shared_ptr<OCIEnv> get_env()
{
// make sure a mutex is involved if CDbaOciNotifier
// can be constructed concurrently.
static weak_ptr<OCIEnv> s_env;
shared_ptr<OCIEnv> env = s_env.lock();
if( ! env )
{
OCIEnv* env_ptr = OCIEnvCreate( ... );
env.reset( env_ptr, Delete_env() );
s_env = env;
}
return env;
}
};
As written you cannot construct CDbaOciNotifier concurrently. You'll need a static mutex to protect s_env if you want that ability.
The weak_ptr needs to be a function local static otherwise you're app might explode if a global or static CDbaOciNotifier is created (static initialization order is undefined).
Does this work for you?
// In .h file
class CDbaOciNotifier
{
// ...
private:
static shared_ptr<OCIEnv> envPtr;
};
// In .cpp file
// Write freeEnvironment as a free function.
shared_ptr<OCIEnv> CDbaOciNotifier::envPtr(new OCIEnv, freeEnvironment);
Related
I'm currently developing a nodejs module, written in C++ and I've been looking for a way to convert a v8::Object to a cv::Mat object from opencv, without any luck for now.
I saw that nan library could help to convert objects, but i couldn't find how, I don't even know if it's possible to convert them in my case.
The v8 juice project would meet my expectations but since it has been abandoned, I just don't know how to do this.
Here is a snippet of what I'm trying to do :
void
BRMatcher::run(const v8::FunctionCallbackInfo<v8::Value>& args)
{
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope scope(isolate);
if (args.Length() < 1)
{
isolate->ThrowException(v8::Exception::TypeError(v8::String::NewFromUtf8(isolate, "Missing parameter [Mat img].")));
return ;
}
if (!args[0]->IsObject())
{
isolate->ThrowException(v8::Exception::TypeError(v8::String::NewFromUtf8(isolate, "Parameter [Mat img] must be an object.")));
return ;
}
v8::Local<v8::Object> cvMat(args[0]->ToObject());
Mat img = ??? // This is where I ended up...
// ...
}
All the posts talking about this on StackOverflow are outdated (older versions or tools that are not working anymore...)
So my questions are: how can I convert the argument I receive in my function to a cv::Mat object ? To any type I want ?
Any help would be appreciated, thanks!
At first I would recommend to look on existing openCV bindings for Node.js like node-opencv.
If you need to bind C++ and JavaScript code, there are several libraries. As an author of one of them, v8pp, I know about several other:
vu8 (abandoned)
v8-juice (abandoned)
Script bindng in cpgf
Embind
As I know, to convert a C++ object into v8::Object all of them use v8::Object::SetAlignedPointerInInternalField() function.
C++ object to v8::Object conversions are usually performed with mapping of a C++ pointer to persistent handle of the V8 object in a map container.
Do have a look on the Nodejs.org C++ addon and Nan tutorials. Though both are a little misleading, they anyhow describe the canonical way. Use Nan over direct V8 APIs since especially this part (was and still) is changing a lot.
With Nan what you're looking for is passing wrapped objects. More precisely this line is the heart of it.
In this fork of Node-OpenCV, I am doing exactly that with cv::Mat in order to make it a first class object for JS-land. Maybe this implementation may help you.
TL;DR
Wrap the object with Nan::ObjectWrap and pass it around. Internally uses v8::SetInternalFieldPointer(); for you. This is basically copy-paste-able.
// lib/mat.js
var cv = require('./bindings')('addon');
function Mat() {
}
/**
* returns the wrapped c++ object
* [arguments optional]
*/
Mat.prototype.createMat = function (a) {
var args = Array.prototype.slice.call(arguments);
return cv.Mat.createMat(args[0])
}
// src/addon.cc
// just initializes all your modules. Magic happening in mat.h and matwrap.h
// matwrap.cc is the implementation of the wrapped object. mat.cc holds
// JS-libarary specific methods
#include <nan.h>
#include "opencv.h"
#include "imgproc.h"
#include "mat.h"
#include "matwrap.h"
void InitAll(v8::Local<v8::Object> exports) {
Opencv::Init(exports);
ImgProc::Init(exports);
Matwrap::Init();
Mat::Init(exports);
}
NODE_MODULE(addon, InitAll)
Important stuff here...
// src/matwrap.h
#ifndef MATWRAP_H
#define MATWRAP_H
#include <opencv2/opencv.hpp>
#include <nan.h>
class Matwrap : public Nan::ObjectWrap {
public:
static void Init();
static v8::Local<v8::Object> NewInstance(v8::Local<v8::Value> arg);
cv::Mat Val() const { return val_; }
private:
Matwrap();
~Matwrap();
static Nan::Persistent<v8::Function> constructor;
static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);
cv::Mat val_;
};
#endif
...and here you're are wrapping it (basically that's it; follow below for consumption):
// src/matwrap.cc
#include <node.h>
#include "matwrap.h"
#include <opencv2/opencv.hpp>
Matwrap::Matwrap() {};
Matwrap::~Matwrap() {};
Nan::Persistent<v8::Function> Matwrap::constructor;
void Matwrap::Init() {
Nan::HandleScope scope;
// Prepare constructor template
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Matwrap").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
constructor.Reset(tpl->GetFunction());
}
void Matwrap::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
// wrap it...
Matwrap* obj = new Matwrap();
cv::Mat src;
obj->val_ = src;
obj->Wrap(info.This());
// return wrapped here...
info.GetReturnValue().Set(info.This());
}
v8::Local<v8::Object> Matwrap::NewInstance(v8::Local<v8::Value> arg) {
Nan::EscapableHandleScope scope;
// const unsigned argc = 1;
// v8::Local<v8::Value> argv[argc] = { arg };
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
v8::Local<v8::Object> instance = cons->NewInstance();
return scope.Escape(instance);
}
For consumption you could do stuff like this:
// lib/mat.js
/**
* Returns true if the array has no elements.
* #param {Object} mat - native cv::Mat
* #return {Boolean}
*/
Mat.prototype.empty = function (mat) {
var args = Array.prototype.slice.call(arguments);
return cv.Mat.empty(args[0])
}
// src/mat.h
// This is your API
#ifndef MAT_H
#define MAT_H
// #include <opencv2/opencv.hpp>
#include <nan.h>
class Mat : public Nan::ObjectWrap {
public:
static void Init(v8::Local<v8::Object> exports);
private:
explicit Mat(double value = 0);
~Mat();
static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);
static void CreateMat(const Nan::FunctionCallbackInfo<v8::Value>& info);
static void Empty(const Nan::FunctionCallbackInfo<v8::Value>& info);
static void Total(const Nan::FunctionCallbackInfo<v8::Value>& info);
static void Type(const Nan::FunctionCallbackInfo<v8::Value>& info);
static Nan::Persistent<v8::Function> constructor;
double value_;
};
#endif
// src/mat.cc
#include "mat.h"
#include "matwrap.h"
#include <opencv2/opencv.hpp>
Nan::Persistent<v8::Function> Mat::constructor;
Mat::Mat(double value) : value_(value) {
}
Mat::~Mat() {
}
void Mat::Init(v8::Local<v8::Object> exports) {
Nan::HandleScope scope;
// Prepare constructor template
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Mat").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
Nan::SetPrototypeMethod(tpl, "createMat", CreateMat);
Nan::SetPrototypeMethod(tpl, "empty", Empty);
Nan::SetPrototypeMethod(tpl, "total", Total);
Nan::SetPrototypeMethod(tpl, "type", Type);
constructor.Reset(tpl->GetFunction());
exports->Set(Nan::New("Mat").ToLocalChecked(), tpl->GetFunction());
}
void Mat::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
if (info.IsConstructCall()) {
// Invoked as constructor: `new Opencv(...)`
double value = info[0]->IsUndefined() ? 0 : info[0]->NumberValue();
Mat* obj = new Mat(value);
obj->Wrap(info.This());
info.GetReturnValue().Set(info.This());
} else {
// Invoked as plain function `Opencv(...)`, turn into construct call.
const int argc = 1;
v8::Local<v8::Value> argv[argc] = { info[0] };
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
info.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
}
void Mat::CreateMat(const Nan::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(Matwrap::NewInstance(info[0]));
}
void Mat::Empty(const Nan::FunctionCallbackInfo<v8::Value>& info) {
Matwrap* obj = Nan::ObjectWrap::Unwrap<Matwrap>(info[0]->ToObject());
// check through cv::Mat::empty()
if (obj->Val().empty()) {
// return JS bool
info.GetReturnValue().Set(Nan::True());
} else {
// TODO: logically not correct
info.GetReturnValue().Set(Nan::False());
}
}
I am very new to C++.
I have a class, and I want to create a thread inside a class's function. And that thread(function) will call and access the class function and variable as well.
At the beginning I tried to use Pthread, but only work outside a class, if I want to access the class function/variable I got an out of scope error.
I take a look at Boost/thread but it is not desirable because of I don't want to add any other library to my files(for other reason).
I did some research and cannot find any useful answers.
Please give some examples to guide me. Thank you so much!
Attempt using pthread(but I dont know how to deal with the situation I stated above):
#include <pthread.h>
void* print(void* data)
{
std::cout << *((std::string*)data) << "\n";
return NULL; // We could return data here if we wanted to
}
int main()
{
std::string message = "Hello, pthreads!";
pthread_t threadHandle;
pthread_create(&threadHandle, NULL, &print, &message);
// Wait for the thread to finish, then exit
pthread_join(threadHandle, NULL);
return 0;
}
You can pass a static member function to a pthread, and an instance of an object as its argument. The idiom goes something like this:
class Parallel
{
private:
pthread_t thread;
static void * staticEntryPoint(void * c);
void entryPoint();
public:
void start();
};
void Parallel::start()
{
pthread_create(&thread, NULL, Parallel::staticEntryPoint, this);
}
void * Parallel::staticEntryPoint(void * c)
{
((Parallel *) c)->entryPoint();
return NULL;
}
void Parallel::entryPoint()
{
// thread body
}
This is a pthread example. You can probably adapt it to use a std::thread without much difficulty.
#include <thread>
#include <string>
#include <iostream>
class Class
{
public:
Class(const std::string& s) : m_data(s) { }
~Class() { m_thread.join(); }
void runThread() { m_thread = std::thread(&Class::print, this); }
private:
std::string m_data;
std::thread m_thread;
void print() const { std::cout << m_data << '\n'; }
};
int main()
{
Class c("Hello, world!");
c.runThread();
}
In the below programme i use one boolean variable named check , which is being accessed inside main function by two objects of Tst1 and Test2 . But the value of check variable is not maintained in the programme . we can use static but i want to know some alternative way ..could anyone give me some hints on it ?
Thanks in advance .
Inside jointdeatils.h
#pragma once
class Jointdetails
{
public:
Jointdetails(void);
~Jointdetails(void);
bool check;
};
Inside jointdeatils.cpp
#include "Jointdetails.h"
Jointdetails::Jointdetails(void)
{
check = false ;
}
Jointdetails::~Jointdetails(void)
{
}
Inside analyzer.h
#pragma once
#include "Jointdetails.h"
class Analyzer
{
public:
Analyzer(void);
Jointdetails* GetJointDetails();
Jointdetails* m_ptheCTJointDetails;
~Analyzer(void);
};
Inside analyzer.cpp
#include "Analyzer.h"
#include "stddef.h"
Analyzer::Analyzer(void)
{
m_ptheCTJointDetails = new Jointdetails();
}
Analyzer::~Analyzer(void)
{
}
Jointdetails* Analyzer::GetJointDetails()
{
if(m_ptheCTJointDetails)
return m_ptheCTJointDetails;
else
return NULL;
}
Inside Test1.h
#pragma once
#include "Analyzer.h"
class Tst1
{
public:
Tst1(void);
Analyzer *analyzer1 ;
public:
~Tst1(void);
};
Inside Test1.cpp
#include "Tst1.h"
Tst1::Tst1(void)
{
analyzer1 = new Analyzer ;
}
Tst1::~Tst1(void)
{
}
Inside Test2.h
#pragma once
#include "Analyzer.h"
class Test2
{
public:
Test2(void);
Analyzer *analyzer2 ;
public:
~Test2(void);
};
Inside Test2.cpp
#include "Test2.h"
Test2::Test2(void)
{
analyzer2 = new Analyzer ;
}
Test2::~Test2(void)
{
}
Inside main.cpp
#include "Test2.h"
#include "Tst1.h"
#include "stdio.h"
int main()
{
Tst1 *test1 = new Tst1 ; //check = false
Test2 *test2 = new Test2 ; //check = false
test1->analyzer1->GetJointDetails()->check = true ;
if(test2->analyzer2->GetJointDetails()->check )
printf("Check value is changed");
else
printf("Check value is not changed");
return 0 ;
}
There are only two possible ways to do so:
Use static storage data
Pass automatic or dynamic storage data as parameters to destination functions/ctors
Way #1 is more handy as you can access such data directly from any function. But it shall be considered as bad design because it almost the same thing as evil global variables.
Way #2 is more correct (see answer by justin for example) but could be a bit irritating - you will need to pass required data as parameter to each required function and/or store data as class data member. Not a pleasant work in case of many classes/nested calls.
Nevertheless, if you don't care on drawbacks of way #1 consider singleton-on-demand concept. It allows to use static data in more dynamic way - create on demand, share access by several users and destroy when nobody use it anymore. See example (several details, includes etc skipped for brevity):
JointDetails.h
class JointDetails
{
// Actual class definition
// ...
public:
// Function accessing to JointDetails instance
static std::shared_ptr<JointDetails> Get();
};
JointDetails.cpp
std::shared_ptr<JointDetails> JointDetails::Get()
{
static std::weak_ptr<JointDetails> s_trackInstance;
if(s_trackInstance.expired())
{
auto instance = std::make_shared<JointDetails>();
s_trackInstance = instance;
return instance;
}
return s_trackInstance.lock();
}
Analyzer.h
// All instances of Analyzer share the same instance of JointDetails.
// But JointDetails instance is created dynamically only when first instance of
// Analyzer is created and destoyed when the last instance of Analyzer is destroyed.
class Analyzer
{
std::shared_ptr<JointDetails> m_details;
public:
Analyzer(): m_details(JointDetails::Get()) {}
const JointDetails& GetDetails() const { return *m_details; }
};
You're either going to have to make check static, or JointDetails a singleton (which also uses the static keyword).
If you make check static, you are saying that all instances of JointDetails have the same check.
If you make JointDetails a singleton, then you're saying that every reference to a JointDetails object is the same object, so your Tst1 and your Test2 will both have a pointer to the same object.
I think the latter is what you're looking for:
Jointdetails.h
#pragma once
class Jointdetails
{
public:
~Jointdetails(void);
bool check;
static Jointdetails* getInstance();
private:
Jointdetails(void);
};
Jointdetails.cpp
#include "Jointdetails.h"
Jointdetails::Jointdetails(void)
{
check = false ;
}
Jointdetails::~Jointdetails(void)
{
}
Jointdetails* Jointdetails::getInstance() {
static Jointdetails s_instance;
return &s_instance;
}
Analyzer.cpp
Analyzer::Analyzer(void)
{
m_ptheCTJointDetails = Jointdetails::getInstance();
}
0) you needn't use new so often.
1) you can construct your objects with the joint details as a parameter in your constructor.
To illustrate:
class Tst1 {
public:
Tst1(Jointdetails& pJointdetails) : analyzer1(pJointdetails) {
}
Analyzer analyzer1;
public:
~Tst1(void);
};
int RunProgram(Jointdetails& pJointdetails) {
Tst1(pJointdetails);
...
}
int main() {
Jointdetails jointdetails;
const int result(RunProgram(jointdetails));
return result;
}
I've got problems passing a member function of a C++ CLI class to a native C callback from a library.
To be precise its the Teamspeak 3 SDK.
You can pass a non member function using the following code without problem:
struct ClientUIFunctions funcs;
/* Initialize all callbacks with NULL */
memset(&funcs, 0, sizeof(struct ClientUIFunctions));
funcs.onConnectStatusChangeEvent = onConnectStatusChangeEvent;
But I need to pass a pointer to a member function, for example:
funcs.onConnectStatusChangeEvent = &MyClass::onConnectStatusChangeEvent;
Any other idea how to use the event within a non static member function is welcome to.
Thanks in advance!
This can only be done via a static class function because C doesn't know anything about the vtable or what object the function is part of. See below for a C++ and Managed C++ example
This could however be a work around, build a wrapper class which handles all the callbacks you need.
#include <string.h>
struct ClientUIFunctions
{
void (*onConnectStatusChangeEvent)(void);
};
class CCallback
{
public:
CCallback()
{
struct ClientUIFunctions funcs;
// register callbacks
my_instance = this;
/* Initialize all callbacks with NULL */
memset(&funcs, 0, sizeof(struct ClientUIFunctions));
funcs.onConnectStatusChangeEvent = sOnConnectStatusChangeEvent;
}
~CCallback()
{
// unregister callbacks
my_instance = NULL;
}
static void sOnConnectStatusChangeEvent(void)
{
if (my_instance)
my_instance->OnConnectStatusChangeEvent();
}
private:
static CCallback *my_instance;
void OnConnectStatusChangeEvent(void)
{
// real callback handler in the object
}
};
CCallback *CCallback::my_instance = NULL;
int main(int argc, char **argv)
{
CCallback *obj = new CCallback();
while (1)
{
// do other stuff
}
return 0;
}
Another possibility would be if the callback supports and void *args like void (*onConnectStatusChangeEvent)(void *args); which you can set from the plugin. You could set the object in this args space so in de sOnConnectStatusChangeEvent you would have something like this:
static void sOnConnectStatusChangeEvent(void *args)
{
if (args)
args->OnConnectStatusChangeEvent();
}
For managed C++ it should be something like this, however I can't get it to compile because it doesn't like the template brackets..
wrapper.h:
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Text;
namespace Test
{
struct ClientUIFunctions
{
void (*onConnectStatusChangeEvent)(void);
};
public delegate void ConnectStatusChangeEvent(void);
public ref class ManagedObject
{
public:
// constructors
ManagedObject();
// destructor
~ManagedObject();
//finalizer
!ManagedObject();
event ConnectStatusChangeEvent^ OnConnectStatusChangeEvent {
void add(ConnectStatusChangeEvent^ callback) {
m_connectStatusChanged = static_cast<ConnectStatusChangeEvent^> (Delegate::Combine(m_connectStatusChanged, callback));
}
void remove(ConnectStatusChangeEvent^ callback) {
m_connectStatusChanged = static_cast<ConnectStatusChangeEvent^> (Delegate::Remove(m_connectStatusChanged, callback));
}
void raise(void) {
if (m_connectStatusChanged != nullptr) {
m_connectStatusChanged->Invoke();
}
}
}
private:
ConnectStatusChangeEvent^ m_connectStatusChanged;
};
class CCallback
{
public:
static void Initialize(ManagedObject^ obj);
static void DeInitialize(void);
private:
static void sOnConnectStatusChangeEvent(void);
static gcroot<ManagedObject^> m_objManagedObject;
};
}
wrapper.cpp:
#include <string.h>
#include "wrapper.h"
using namespace System;
using namespace Test;
void CCallback::Initialize(ManagedObject^ obj)
{
struct ClientUIFunctions funcs;
// register callbacks
m_objManagedObject = obj;
/* Initialize all callbacks with NULL */
memset(&funcs, 0, sizeof(struct ClientUIFunctions));
funcs.onConnectStatusChangeEvent = sOnConnectStatusChangeEvent;
}
void CCallback::DeInitialize(void)
{
// unregister callbacks
m_objManagedObject = nullptr;
}
void CCallback::sOnConnectStatusChangeEvent(void)
{
if (m_objManagedObject != nullptr)
m_objManagedObject->OnConnectStatusChangeEvent();
}
// constructors
ManagedObject::ManagedObject()
{
// you can't place the constructor in the header but just for the idea..
// create wrapper
CCallback::Initialize(this);
}
// destructor
ManagedObject::~ManagedObject()
{
this->!ManagedObject();
}
//finalizer
ManagedObject::!ManagedObject()
{
CCallback::DeInitialize();
}
gcroot<ManagedObject^> CCallback::m_objManagedObject = nullptr;
int main(array<System::String ^> ^args)
{
ManagedObject^ bla = gcnew ManagedObject();
while (1)
{
// do stuff
}
return 0;
}
Before I present the code which is found at the bottom of this post I would like to talk about the issue and the fix's that I do not desire. Okay basically I've created a GUI from scratch sort of and one requirement I wanted for this was allow components to have their own click executions so if i click a button or tab etc.. It would call Component->Execute(); Well normally you would do something like a switch statement of ids and if that components ID equaled n number then it would perform this action. Well that seemed kinda dumb to me and I thought there has to be a better way. I eventually tried to incorporate a feature in JAVA where you would do like Component.AddActionListener(new ActionListener( public void execute(ActionEvent ae) { })); or something like that and I thought that this feature has to be possible in C++. I eventually came across storing void functions into a variable in which could be executed at any time and modified at any time. However I hadn't noticed an issue and that was this only worked with static functions. So below you'll see my problem. I've patched the problem by using a pointer to SomeClass however this would mean having an individual function call for every class type is there no way to store a function callback to a non-static class member without doing the below strategy? and instead doing a strategy like the commented out code?
//Main.cpp
#include <iostream> //system requires this.
#include "SomeClass.h"
void DoSomething1(void)
{
std::cout << "We Called Static DoSomething1\n";
}
void DoSomething2(void)
{
std::cout << "We Called Static DoSomething2\n";
}
int main()
{
void (*function_call2)(SomeClass*);
void (*function_call)() = DoSomething1; //This works No Problems!
function_call(); //Will Call the DoSomething1(void);
function_call = DoSomething2; //This works No Problems!
function_call(); //Will Call the DoSomething2(void);
SomeClass *some = new SomeClass(); //Create a SomeClass pointer;
function_call = SomeClass::DoSomething3; //Static SomeClass::DoSomething3();
function_call(); //Will Call the SomeClass::DoSomething3(void);
//function_call = some->DoSomething4; //Non-Static SomeClass::DoSomething4 gives an error.
//function_call(); //Not used because of error above.
function_call2 = SomeClass::DoSomething5; //Store the SomeClass::DoSomething(SomeClass* some);
function_call2(some); //Call out SomeClass::DoSomething5 which calls on SomeClass::DoSomething4's non static member.
system("pause");
return 0;
}
//SomeClass.hpp
#pragma once
#include <iostream>
class SomeClass
{
public:
SomeClass();
~SomeClass();
public:
static void DoSomething3(void);
void DoSomething4(void);
static void DoSomething5(SomeClass* some);
};
//SomeClass.cpp
#include "SomeClass.h"
SomeClass::SomeClass(void)
{
}
SomeClass::~SomeClass(void)
{
}
void SomeClass::DoSomething3(void)
{
std::cout << "We Called Static DoSomething3\n";
}
void SomeClass::DoSomething4(void)
{
std::cout << "We Called Non-Static DoSomething4\n";
}
void SomeClass::DoSomething5(SomeClass *some)
{
some->DoSomething4();
}
Secondary Fix for what I'll do not an exact answer I wanted but it meets my needs for now along with allowing additional features which would have become overly complicate had this not existed.
//Component.hpp
#pragma once
#include <iostream>
#include <windows.h>
#include <d3dx9.h>
#include <d3d9.h>
#include "Constants.hpp"
#include "ScreenState.hpp"
#include "ComponentType.hpp"
using namespace std;
class Component
{
static void EMPTY(void) { }
static void EMPTY(int i) { }
public:
Component(void)
{
callback = EMPTY;
callback2 = EMPTY;
callback_id = -1;
}
Component* SetFunction(void (*callback)())
{
this->callback = callback;
return this;
}
Component* SetFunction(void (*callback2)(int), int id)
{
this->callback_id = id;
this->callback2 = callback2;
return this;
}
void execute(void)
{
callback();
callback2(callback_id);
}
}
The syntax for pointers-to-member-functions is as follows:
struct Foo
{
void bar(int, int);
void zip(int, int);
};
Foo x;
void (Foo::*p)(int, int) = &Foo::bar; // pointer
(x.*p)(1, 2); // invocation
p = &Foo::zip;
(x.*p)(3, 4); // invocation
Mind the additional parentheses in the function invocation, which is needed to get the correct operator precedence. The member-dereference operator is .* (and there's also ->* from an instance pointer).