I'm attempting to modify a C++ class in such a way that an Objective C object is one of its instance variables.
In essence, this question is like the reverse of this: C++ classes as instance variables of an Objective-C class
The header file MyCPPClass.h looks like this:
namespace my_namespace{
class MyCPPClass: public my_namespace::OperationHandler {
public:
void someFunc();
private:
void otherFunc();
};
}
And the MyCPPClass.mm file looks like this:
#include "MyCPPClass.h"
#import <Foundation/Foundation.h>
void my_namespace:: MyCPPClass:: someFunc() {
NSLog(#"I can run ObjC here! Yahoo!");
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"download_url_goes_here"]];
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// handle the data
}];
}
void my_namespace:: MyCPPClass:: otherFunc() {
NSLog(#"I can run ObjC here! Yahoo!");
}
The issue here is that I need to store a reference to an object created in someFunc() and then use it in otherFunc(). This object is an instance of NSURLSessionTask. My background in C++ is very limited :(. What is the least intrusive way to do this?
I believe you can store it as a void*, according to this Pass an Objective-C object to a function as a void * pointer
So your header would become:
namespace my_namespace{
class MyCPPClass: public my_namespace::OperationHandler {
public:
void someFunc();
private:
void otherFunc();
void *mySessionTask;
};
}
If you want to send a message to it you first cast it back to what it is supposed to be:
[(NSURLSessionTask*)mySessionTask someMessageWithArg: foo]
Related
I tried to build a wrapper for a C module. The C module will do some CAN communication. To read something there is a read() function where a callback function pointer is passed with.
My idea was to make a Caller class where other classes (in example class A) can inherit from. I have now a problem in function "A::req()" with the comand "readObject()". To have no compiler errors I have to make a static_cast but then during excecution program will not work proberly. I already read that downcast in specialication can be dangerous. I guess my error is coming from that.
How could I solve my problem? Any ideas? Is there a design pattern which I should check?
Thanks.
class A : public Caller
{
public:
void req()
{
//readObject(&A::specializedCallback); // error from compiler
readObject(static_cast<Caller::CbkPtr_t>(&A::specializedCallback)); // has error during excecution, because of downcast?
}
void specializedCallback(void *data);
}
class Caller
{
public:
typedef void (CanIfcCaller::*CbkPtr_t)(void *data);
readObject(CbkPtr_t cbFcnt)
{
cbkFunction = cbFcnt;
Wrapper::readObject(this):
}
void callbackReadObject(void *data)
{
(this->*cbkFunction)(data);
}
private:
CbkPtr_t cbkFunction;
}
class Wrapper // to C function
{
public:
static void readObject(Caller* theCaller)
{
pCaller = theCaller;
read(&Wrapper::callbackReadObject);
}
static void callbackReadObject(void *data)
{
pCaller->callbackReadObject(data);
}
private:
Caller* pCaller;
}
I use Wrapper-Class using pimpl so I can use Objective-C methods while using C++.
Now in my ViewWrapper.hpp I have this:
class ViewWrapper
{
public:
void addSubview(ViewWrapper *view); //method exists in original View.h (Objective-C)
ViewWrapper (void);
~ViewWrapper (void);
private:
struct Impl;
Impl* impl;
};
In my ViewWrapper.mm:
//ViewWrapper.mm
#import "ViewWrapper.hpp"
#import "View.h" // original Objective-C header
struct ViewWrapper::Impl
{
View* obj;
};
ViewWrapper::ViewWrapper() : impl(new Impl)
{
impl->obj = [[View alloc] init];
}
void ViewWrapper::addSubview(ViewWrapper *view)
{
[impl->obj addSubview:(View *) view]; // <- here is the error
}
Now in my main.cpp I use it like this:
// main.cpp
ViewWrapper *wrapper1 = new ViewWrapper();
ViewWrapper *wrapper2 = new ViewWrapper();
wrapper1->addSubview(wrapper2);
Now when I try to compile it, I get the error message
"Thread 1:EXC_BAD_ACCESS(code=2, address=0x105)" in my ViewWrapper.mm
I guess my problem is that this is not the correct way of casting ViewWrapper to View. Any other method works just fine (e.g. const char* to NSString and so on..)
Can anyone help me? If you need more info, I'll try to add it as good as I can.
I solved it myself. If anyone faces the same problem, I changed my addSubview-method like that:
[impl->obj addSubview:(UIView *) view->impl->obj];
I want to transfer a function pointer in the constructor but get some error Messages...
I my parent class I declared:
class Strip{
public:
typedef void(Strip::*LOG)(const std::string&);
with a function log(const string&)
In my child class I forward declare Strip with class Strip and have somthing like that
class Observable{
public:
Observable(const char &signal,Strip::LOG log,const QCustomPlot *plot);
with a parameter
Strip::LOG log;
When I try to compile I get the error's
Strip::LOG has not been declared
and LOG in class Strip does not name a type
Any Idea how to fix that?
So passing a pointer to a member function presents several issues:
It's a member function as such it will need to have an instance of the class passed into it to work (the implicit this parameter).
It doesn't prevent the class you're passing it to from knowing about the class the function pointer originates so you gain nothing in terms of hiding.
A better way is to declare an Interface and pass that
// ILogger.hpp
// should be completely virtual
struct ILogger{
virtual void log(const ::std::string&) = 0;
};
// Strip.cpp
class Strip : public ILogger{
public:
void log(const ::std::string& data){
// does something
}
};
// Observable.cpp
#include "ILogger.hpp"
class Observable{
public:
Observable(ILogger* logger);
};
// some other file that knows about and constructs both
// has to be a pointer allocated to new to make the Vtables work
::std::unique_ptr<Strip> s(new Strip());
// pass in the pointer to an instance of a class that implements ILogger
Observable observed(s.get());
Using an interface means you can completely abstract the two classes apart and Observable need not know anything about the instance being passed to it other than it implements ILogger. Internally Observable can call the logger by just calling logger->log.
May be this code can be usefull (compiled w/o errors):
#include <iostream>
using namespace std;
class Strip{
public:
typedef void(Strip::*LOG)(const std::string&);
void log(const string& s)
{
cout << "log() called\n";
}
};
class Observable{
public:
Observable( Strip::LOG l )
{
Strip s;
(s.*l)("string");
}
};
int main() {
Strip::LOG log = &Strip::log;
Observable o( log );
return 0;
}
http://ideone.com/RD4K1r
EDIT 2:
Here is a simple summary of what I want to do (I think):
I want to dynamically create global instances based on conditions that are calculated at run time.
You can skip to EDIT1 if you'd like to take a look at sample code, but at this point, the above bolded-text is probably the easiest to understand...
END EDIT 2.
My question is about polymorphism and inheritance. Specifically, I want to know if there is a way I could inherit functions and pointers from another class.
I have a class called Globals which contains various pointers to objects to other classes as well as various functions. Instead of copy/pasting code, I'll write up a simple example:
(I've removed header guards for simplicity and cleanliness)
The following is my globals.h and globals.cpp, respectively:
// Example of globals.h
#include <iostream>
#include <cstdio>
using namespace std;
class Globals {
public:
Globals ();
virtual ~Globals ();
void function1(char*);
void function2();
class Input *input;
class Error *error;
};
// Example of globals.cpp
#include "globals.h"
Globals::Globals()
{
input = new Input();
error = new Error();
}
void Globals::function1(char*nm)
{
cout << nm << endl;
}
Now, in my code for my Input class, say I want to use the function1(char*) method, would this be possible without passing an object to the Input class? What I mean by this is that I currently have my Input class being passed a *globals object, so then I could call the function like so: globals->function2();. But this can get very messy if I have a lot of functions within different classes. Additionally, is there a way I could use the Error pointer to object initialized in Globals? If Error had a function called error_func(), how could I be able to call it like so: error->error_func() from within my Input functions?
Thanks, and I apologize if I were too confusing in my question. I'll be happy to elaborate if needed.
Amit
EDIT 1: Added a simplified code to present what I want to do in a clearer way
// Example of globals.h
#include <iostream>
#include <cstdio>
#include "input.h"
#include "error.h"
using namespace std;
class Globals {
public:
Globals ();
virtual ~Globals ();
class Input *input;
class Error *error;
};
// Example of globals.cpp
#include "globals.h"
Globals::Globals()
{
input = new Input();
error = new Error();
}
// Example of input.h
#include "globals.h"
class Input {
public:
Input();
virtual ~Input();
}
// Example of input.cpp
#include "globals.h"
Input::Input()
{
error->print("Hello\n"); // <-- THIS is really what I want to accomplish (without being sent a globals object and say globals->error->print();
}
// Example of error.h
#include "globals.h"
class Error {
public:
Error() { }
virtual ~Error() { }
void print(char*);
}
// Example of error.cpp
#include "globals.h"
Error::print(char* nm)
{
cout << nm << endl;
}
If I'm understanding your question right, functions are automatically "inherited", at least for the purposes you need.
For example, your global class has two methods, function1(char*) and function2(). If you make a class:
class Descendent
: public Global
{ };
int main()
{
Global * global = new Global();
Global * desc = new Descendant();
char * str = "string";
// These two will run the same function:
global->function1(str);
desc->function1(str);
}
To prevent that (functions being called based on the current type), you must use virtual, like:
class Global
{
virtual void function1(char *);
};
class Descendant
{
virtual void function1(char *);
};
int main()
{
Global * global = new Global();
Global * desc = new Descendant();
char * str = "string";
// These two will NOT run the same function:
global->function1(str);
desc->function1(str);
}
Now, I'm not entirely sure, but the singleton idiom may be of use here, depending on just how global your Global is. In that case, you would have a global like:
class Global
{
static Global * GetSingleton()
{
if (!Global::m_Instance) Global::m_Instance = new Global();
return Global::m_Instance;
}
void function1(char *);
static Global * m_Instance;
};
class Descendant
{
void function1(char *)
{
Global * global = Global::GetGetSingleton();
// ...
}
};
There are a variety of ways to work with globals and functions being needed between classes. One of these may be it, depending on what exactly you're doing. If not, I'll try to edit and suggest one that does work.
I'm imagining you have a situation like this:
struct A {
void f();
};
struct B {
void g();
};
struct C : virtual A, virtual B {
C(A *ap, B *bp)
: A(ap), B(bp) // This doesn't actually work -- theoretical
{
}
void h()
{
f(); // calls A::f()
g(); // calls B::g();
}
};
Normally, when you create a C, you would be creating new As and Bs, but you would like to re-use existing ones instead, but still treat it like inheritance so that you don't have to explicitly specify which object to call.
Unfortunately, C++ doesn't support this. There are a couple of options:
You can make proxy classes that defer the function calls:
struct AProxy {
AProxy(A *ap) : a(*ap) { }
void f() { a.f(); }
A &a;
};
struct BProxy {
BProxy(B *bp) : b(*bp) { }
void g() { b.g(); }
B &b;
};
struct C : AProxy, BProxy {
C(A *ap,B *bp) : AProxy(ap), BProxy(bp) { }
void h()
{
f(); // calls AProxy::f() which calls a.f()
g(); // calls BProxy::g() which calls b.g()
}
};
This may help if you are using A's and B's in lots of different places.
If instead, you don't have many classes, but lots of calls to f() and g(), you might just do this:
struct C {
C(A *ap,B *bp) : a(*ap), b(*bp) { }
void f() { a.f(); }
void g() { b.g(); }
void h1()
{
f(); // well at least the call is clean here
g();
}
void h2()
{
f(); // and clean here
g();
}
A &a;
B &b;
};
If you don't have either of these cases, then just using the proper object each time like you were doing may be best.
Updated response:
Its sounds like what you want is actually the Factory pattern. I'm going to use logging as an example, where I assume that in one configuration you want to log and in another you might not want to:
// logger_interface.h
class LoggerInterface {
public:
virtual ~LoggerInterface() {}
virtual void Log(const string& message) = 0;
protected:
LoggerInterface() {}
};
The first step is to create a pure virtual interface representing the behavior that is configurable as in the example above. We will then create a factory function that can construct one based on configuration:
// logger_factory.h
LoggerInterface* CreateLogger(LoggerOptions options);
When implementing the factory, we keep the different implementations hidden:
// logger_factory.cc
class DoNotLogLogger : public LoggerInterface {
public:
DoNotLogLogger() {}
virtual ~DoNotLogLogger() {}
virtual void Log(const string& message) {}
};
class LogToStdErrLogger : public LoggerInterface {
public:
LogToStdErrLogger() {}
virtual ~LogToStdErrLogger() {}
virtual void Log(const string& message) {
std::cout << message << std::endl;
}
};
LoggerInterface* CreateLogger(LoggerOptions options) {
if (options.IsLoggingEnabled() && options.ShouldLogToStdErr()) {
return new LogToStdErrLogger;
}
return new DoNotLogLogger;
}
There is no reason why the object that you create dynamically in this way needs to be global; in fact, making it global is a really bad idea. Just create it where you need it, and pass it as a parameter to the functions that need it.
Original response:
Inheritance isn't the word you are looking for. Basically, what you are asking for is a static function:
class ClassName {
public:
static void methodName();
};
In the above, methodName can be invoked using ClassName::methodName() without requiring a specific instance of the class named ClassName. However, if you are to do this, it is more consistent with C++ style conventions to make it a freestanding function in a namespace like:
namespace name_of_namespace {
void functionName();
}
The above is invoked using name_of_namespace::functionName() as in the previous example, except with the benefit that it is easier to change or remove the prefix (e.g. via a using directive).
NOTE: from a design standpoint, you should only use a freestanding or static function if it does not rely on any state (other than the parameters passed to it) and there is no possibility of alternative implementations. As soon as there is state or alternative implementations, you really should pass around an object encapsulating this state, even if it is a pain to do, since passing around the object makes it easier to configure, makes it easier to mock-out in tests, and avoids threading issues.
I'm writing a game for the iPhone. Almost all the code is written in C++. Now I'd like to create a new thread using NSThread (I want to use the runLoop).
It's possible to mix objective-C and C++ if the code is written in a .mm file, which I did.
The problem is, that for creating a NSThread
NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:#selector(workerThreadFunction:) object:nil];
[myThread start];
I need to pass "self" which (as far as I understand it) an Objective-C "id" - and a c++ object is not an objective-c object.
So - is there a way to use NSThread in a c++ aplication or am I forced to use pthreads?
Thanks!
can I somehow create an objective-C object which - in it's constructor - takes a c++ function pointer as an argument which it calls later?
Sure. Like this:
//The C++ base
class ThreadBase
{
virtual void Run() = 0;
};
typedef ThreadBase * (*ThreadCreator)();
//The ObjC wrapper
#interface ThreadStarter:NSObject
{
ThreadCreator TheCreator;
}
-(void)Run;
-(id)init:(ThreadCreator)tc;
#end
#implementation ThreadStarter
-(id)init:(ThreadCreator)tc
{
TheCreator = tc;
return [super init];
}
-(void)Run
{
(*TheCreator)()->Run();
}
#end
//
class MyThread: public ThreadBase
{
//...
};
ThreadBase *MyThreadCreator()
{
return new MyThread();
}
//And finally usage
ThreadStarter *tc = [[ThreadStarter alloc]init:MyThreadCreator];
NSThread* myThread = [[NSThread alloc] initWithTarget:tc selector:#selector(Run) object:nil]; [myThread start];
It's parametrized by a creator function because you wanted it so. But you can parametrize by class as well.
"can I somehow create an objective-C object which - in it's constructor - takes a c++ function pointer as an argument which it calls later?"
Yes, but its rather ugly.
First, define a callback baseclass, and a templated version. This can go into a generic .h file that can be #included from .cpp and .mm files. Also define a basic CThread class:
// Thread.h
#pragma once
#include <objc/objc.h> // for a cpp compatible definition of id
class Callback{
public:
virtual void operator()(void)=0;
};
template<class T>
class ClassCallback : public Callback {
T* _classPtr;
typedef void(T::*fncb)(void);
fncb _cbProc;
public:
ClassCallback(T* classPtr,fncb cbProc):_classPtr(classPtr),_cbProc(cbProc){}
virtual void operator()(void){
(_classPtr->*_cbProc)();
}
};
class CThread {
id _thread;
public:
void Start(Callback* cb);
};
Next, put the implementation of CThread, and its obj-c buddy object, in a .mm file:
// Thread.mm
#import <Cocoa/Cocoa.h>
#import "Thread.h"
#interface ThreadStarter:NSObject
{
Callback *theCallback;
}
-(void)Run;
-(id)init:(Callback*)cb;
#end
#implementation ThreadStarter
-(id)init:(Callback*)cb
{
theCallback = cb;
return [super init];
}
-(void)Run
{
theCallback();
}
#end
void CThread::Start(Callback* cb){
_thread = [[ThreadStarter alloc] init:cb];
[NSThread detachNewThreadSelector:#selector(Run)
toTarget:_thread
withObject:nil];
}
};
And then, in your application's cpp file, you can:
// MyClass.cpp (doesn't even have to be .mm)
#include "Thread.h"
class MyClass {
CThread _myThread;
void SomeArbMethod(){
}
public:
MyClass(){
_myThread.Start( new ClassCallback<MyClass>(this,&MyClass::SomeArbMethod));
}
};
You cannot derive C++ classes from Objective C classes and vice versa. Design a wrapper ObjC object that would instantiate and call (but not inherit from) the C++ one. This is generally called "containment and delegation".
Or you can use POSIX threads instead of NSThread.
For a C++-style rephrasing of my previous answer:
//The C++ base
class ThreadBase
{
virtual void Run() = 0;
};
//The ObjC wrapper
#interface ThreadStarter:NSObject
{
ThreadBase *TheThread;
}
-(void)Run;
-(id)init:(ThreadBase)tb;
#end
#implementation ThreadStarter
-(id)init:(ThreadBase)tb
{
TheThread = tb;
return [super init];
}
-(void)Run
{
TheThread->Run();
}
#end
//
class MyThread: public ThreadBase
{
//...
};
//And finally usage
MyThread *Thread = new MyThread();
ThreadStarter *tc = [[ThreadStarter alloc]init:Thread];
NSThread* myThread = [[NSThread alloc] initWithTarget:tc selector:#selector(Run) object:nil];
[myThread start];
Much cleaner this way, IMHO. If you're insist that the thread start routine is an arbitrary function in an atrbitrary class not of your creation, here's your answer:
class MyThread: public ThreadBase, public MyOtherObject
{
void Run()
{
DoWork(); //Function defined in MyOtherObject
}
}
You see, if you want to parametrize by member function, you have to parametrize by both function and class. And class cannot be a run-time variable in C++.