In a C++CLI project I make a call to a native object on an event, I'd like to be able to call a C++/CLI function from the native C++ when this event is triggered. I have following code at the moment, but it returns the error that PickObjects() is not a member of ManagedClass. Is calling back to a static C++CLI method possible?
#pragma once
#include "Stdafx.h"
#include "ManagedClass.h"
namespace Unmanaged
{
public class EventHandlers
{
public:
static void OnClick(customObject* caller, void *calldata)
{
//call managed method, can get here from CLI
ManagedClass::ManagedObject::PickObjects();
}
};
}
Here is the C++CLI code snippet, everything here appears to run fine:
namespace ManagedClass
{
public ref class ManagedObject
{
public:
static void PickObjects()
{
//pick stuff when called
}
};
}
EDIT: Got it working, the error was definitely related to how Visual Studio compiled the files. Will update with solution momentarily. Thanks to Matthias for the help.
It seems as though the classes were not getting compiled in the correct order. Adding the EventHandlers class to the end of ManagedClass got things working.
namespace ManagedClass
{
public ref class ManagedObject
{
public:
static void PickObjects()
{
//pick stuff when called
}
};
public class EventHandlers
{
public:
static void OnClick(customObject* caller, void *calldata)
{
ManagedClass::ManagedObject::PickObjects();
}
};
}
Yes, calling a static method out of another static method is possible.
In this case it sounds like you haven't declared ManagedClass::PickObjects() properly. You may show us the code (header should be enough) of it.
Related
I'm struggling with a piece of code and at this point I'm questioning if what I'm trying to achieve is even possible.
Below is the code of the various DLL and the actual piece of code that's giving me an headache
First DLL:
// DLL_A
// This DLL is the main SDK which gives me the capability to create and manage extensions
class IViewportExtensionBase
{
public:
virtual ~IViewportExtensionBase();
...
};
template<typename ExtensionType>
class IViewportExtension : public IViewportExtensionBase
{
protected:
IViewportExtension()
: IViewportExtensionBase(ExtensionType::_GetName())
{ }
};
class ExtensionsManager
{
public:
static IViewportExtensionBase* GetExtension(const std::string& extensionName)
{
return _extensions[extensionName];
}
private:
std::unordered_map<std::string, IViewportExtensionBase*> _extensions;
};
Second DLL:
// DLL_B
// This is another library of the SDK which links DLL_A to add a custom capabilities to the extensions
class ViewportExtensionAdditions
{
public:
virtual ~ViewportExtensionAdditions()
{ }
virtual void CustomAddition()
{ }
};
template<typename ExtensionType>
class ICustomViewportExtension : public IViewportExtension<ExtensionType>, public ViewportExtensionAdditions
{ };
Extension DLL
// DLL_EXTENSION
// This DLL contains the actual extension which implements the interface defined by DLL_B 8of course this links DLL_B too)
class ViewportExtension_A : public ICustomViewportExtension<ViewportExtension_A>
{
public:
void CustomAddition() override;
...
}
Actual program giving me the error:
// This is a piece of code of the final program which loads the extensions and then tries to call the custom capabilities added by DLL_B
// This program knows about the headers of both DLL_A and DLL_B and links them, but it doesn't know about the headers of DLL_EXTENSION which
// is dynamically loaded by the extensions manager
auto extension = (ViewportExtensionAdditions*)ExtensionsManager::GetExtension("ViewportExtension_A");
if (extension != nullptr)
{
// This call doesn't work, meaning that is never calls the overridden method in ViewportExtension_A
// but calls some other method which looks like the virtual table is somewhat off
extension->CustomAddition();
}
I'm afraid that deriving a class injecting another (what I'm doing in DLL_B) and then casting to that other class (what I'm doing in the acqual program) is not possible.
If actually turns out it's not possible, what could be a way to achieve what I'm trying to do?
I'm very new to C++ and I'm struggling on a project where I need to transmit a reference to a callback method between to different class instances. I know that this subject is a pretty common issue for C++ beginners. I understand that member function pointers are different from the "standard" function ones, but I cannot find any post that adresses my specific problem (but may be it is because, given my lack of experience with C++ I don't understand the provided answers).
The system I try to develop is based on :
A ControllerManager class (which is a Singleton)
A Controller base class
Some specific Controller classes (FanController, LighController, etc) which inherits from the Controller class
What I would like to do is from let say a FanController instance to call an addCallback method of the ControllerManager class. This method would take as a parameter a pointer to any public method of the FanController so that the ControllerManager could made a callback to this method later (I must specify that the ControllerManager include the definition of the Controller class but doesn't know anything about the FanController class)
So far I didn't found any working solution, the only thing I managed to get is a very poor workaround (for simplicity, only relevant methods are indicated) :
class Controller {
public:
virtual void callback();
};
class FanController:Controller {
public:
virtual void callback();
};
class ControllerManager
{
private:
static ControllerManager *_instance;
Controller *_controller;
public:
void addCallback(Controller * controller)
{
_controller = controller;
}
static void periodicCallback()
{
_instance->_controller->callback();
}
};
At runtime the FanController instance provides a reference of herself to the ControllerManager singleton :
ControllerManager::getInstance()->addController(this);
and the ControllerManager can make a call to the callback method of the FanController instance:
_instance->_controller->callback();
This workaround is very limited since it allows only calls to methods declared by the parent Controller class.
What I would to implement is a system that allows the specifics controllers to provide references of their member methods (which doesn't exist in the Controller class) to the ControllerManager so that it can make calls to those methods.
If someone can help me I thanks him/her in advance.
The modern way of tackling this is to squirrel away the method's binding in a lambda.
#include <functional>
#include <vector>
class Controller {
std::vector<std::function<void()>> callbacks_;
public:
void addCallback(std::function<void()> cb) {
callbacks_.push_back(std::move(cb));
}
void periodicCallback() {
for(const auto& cb : callbacks_) {
cb();
}
}
};
class Fan {
public:
void whatever() {}
void register_in_controller(Controller* tgt) {
tgt->addCallback([this]{whatever();});
}
};
I would like to wrap a native library with C++/CLI. It's work with primitive type. But in the following case, it's more complicated :
interface ISampleInterface
{
void SampleMethod();
}
public ref class NativeClassWrapper {
NativeClass* m_nativeClass;
public:
NativeClassWrapper() { m_nativeClass = new NativeClass(); }
~NativeClassWrapper() { delete m_nativeClass; }
void Method(ISampleInterface ^i) {
???
m_nativeClass->Method(i);
}
};
How to wrap this ? Because the native code C++ doesn't know the ISampleInterface type... (Same question with a virtual class)
Thanks you.
There are some mistakes in the code snippet. Let's start with a clean example, declaring the native class first:
#pragma unmanaged
class INativeInterface {
public:
virtual void SampleMethod() = 0;
};
class NativeClass {
public:
void Method(INativeInterface* arg);
};
And the managed interface:
#pragma managed
public interface class IManagedInterface
{
void SampleMethod();
};
So what you need is a native wrapper class that derives from INativeInterface so that you can pass an instance of it to NativeClass::Method(). All that this wrapper has to do is simply delegate the call to the corresponding managed interface method. Usually a simple one-liner unless argument types need to be converted. Like this:
#pragma managed
#include <msclr\gcroot.h>
class NativeInterfaceWrapper : public INativeInterface {
msclr::gcroot<IManagedInterface^> itf;
public:
NativeInterfaceWrapper(IManagedInterface^ arg) : itf(arg) {};
virtual void SampleMethod() {
itf->SampleMethod();
}
};
Now your method implementation becomes easy:
void Method(IManagedInterface^ i) {
NativeInterfaceWrapper wrap(i);
m_nativeClass->Method(&wrap);
}
If your native class needs to callback into .NET code, you need to use the gcroot template. Wuth this you can store the managed object in an unmanaged class. In this unmanaged class you can then use a native "callback" and then use the member stored in `gcroot´ to callback into managed code (ISampleInterface).
See also:
How to: Declare Handles in Native Types
How to: Hold Object Reference in Native Function
Best Practices for Writing Efficient and Reliable Code with C++/CLI
I'm trying to make a connection between a function in one class so that I can call it in another class. The answers I've found are either too specific or maybe I'm missing something because I cannot for the life of me figure out what I'm doing wrong. Also, I'm a bit new to the boost library so please excuse any dumb questions I may ask.
The setup for my workflow is basically this...
class MyClass : public BaseClass {
void setup();
void myFunc(datatype);
OtherClass myOtherClass;
}
void setup()
{
OtherNamespace::addListener(this, myOtherClass);
}
namespace OtherNamespace {
class OtherClass {
signals::signal<void (datatype)> myConnection;
}
template<class A, class B>
void addListener(A * app, B & connection)
{
connection.myConnection.connect( 'I don't know what to do here' );
}
}
Basically, the addlistener function won't make the connection between the signal and the function. I know that where I don't know what to do I'm doing something wrong but I just can't figure out what about it is wrong. I'm making this as a helper function so that I can pass functions from one class to another then call them when they're attached. I'm trying to create a domino event from a websocket connection and I am clearly missing something very important. Any help would be truly appreciated.
I'm on xcode and boost and macbook pro.
You should connect to the signal a matching slot, which is a callable having the appropriate signature. The best solution is to leave the slot creation to the caller of your addListener function (the following is your code, in SSCCE form):
#include <boost/signals2.hpp>
typedef int datatype;
class BaseClass
{};
namespace OtherNamespace
{
class OtherClass
{
public:
boost::signals2::signal<void (datatype)> myConnection;
};
template<class A, class B>
void addListener(A app, B & connection)
{
connection.myConnection.connect(app);
}
}
class MyClass : public BaseClass
{
public:
void setup();
void myFunc(datatype)
{}
OtherNamespace::OtherClass myOtherClass;
};
void MyClass::setup()
{
// let the caller decide how to make the slot
OtherNamespace::addListener(boost::bind(&MyClass::myFunc, this, _1), myOtherClass);
}
I have a central list of implementations of an interface and would like for derived classes to be able to register themselves in that list without having to add them in some central place. For example:
// interface.h
struct MyInterface;
std::vector<MyInterface*>& InterfaceList();
struct MyInterface {
MyInterface() {
InterfaceList().push_back(this);
}
virtual ~MyInterface() {}
// ...
};
// derived.cpp
#include "interface.h"
class MyImplementation: public MyInterface {
public:
MyImplementation() {
}
// ...
};
MyImplementation impl;
This doesn't seem to work. For reasons I don't understand, the constructor of MyInterface never gets called - I would have thought that the instance of the derived class would call it at startup. I know it's possible to do something along these lines since I've seen other libraries doing it - but haven't managed to figure out what it is that I'm doing wrong.
Thanks :)
Edit: Sorry, missed a pair of braces and a reference. InterfaceList() is a function that returns a reference to a vector.
Edit part 2: Have now got it working in a reduced example, but can't get it to work in the files for the derived implementations - but that technique is working in another project. There must be something slightly different in those files which is causing it to fail - but it appears the problem isn't in the code I posted. Don't really want to post big chunks of my employer's projects though so I guess I'll have to keep fiddling myself. Thanks for the suggestions so far though :)
You example does not compile under VS2008. What compiler are you using? When you change the second line in interface.h to
std::vector<MyInterface*> InterfaceList;
it works correctly. Just drop the braces.
I had a similar problem recently, and found that the simplest solution was to create a templated base class that was responsible for registering all of my implementations.
The base class contains a static variable, of templated type T, and this is registered with the central list. At runtime, each implementation would create its own static object and in the process of creating itself would register with the central list.
#include <iostream>
#include <vector>
class ITestInterface
{
public:
virtual void Execute() = 0;
};
std::vector<ITestInterface *> InterfaceList;
template <class T> class BaseClass :
public ITestInterface
{
public:
virtual void Execute() = 0;
protected:
BaseClass()
{
InterfaceList.push_back(&s_thing);
}
private:
static T s_thing;
};
template <class T> T BaseClass<T>::s_thing;
class ImplementationOne :
public BaseClass<ImplementationOne>
{
public :
ImplementationOne():
BaseClass()
{
;
}
void Execute()
{
std::cout << "ImplementationOne Execute\r\n";
}
};
class ImplementationTwo :
public BaseClass<ImplementationTwo>
{
public :
ImplementationTwo():
BaseClass()
{
;
}
void Execute()
{
std::cout << "ImplementationTwo Execute\r\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<ITestInterface *>::iterator it = InterfaceList.begin();
for(; it != InterfaceList.end(); it++)
{
(*it)->Execute();
}
}
The thing to remember with this code is that the line
static T s_thing;
does not result in a single s_thing, rather because a template is a type-generator there is one static s_thing for each derived class.
The output is
ImplementationOne Execute
ImplementationTwo Execute
This code works in VS2010.
This is the issue:
std::vector<MyInterface*> InterfaceList();
should be
std::vector<MyInterface*> InterfaceList;
Following definition of InterfaceList is a kind of function declaration which returns std::vector
std::vector<MyInterface*> InterfaceList();
Change this to
std::vector<MyInterface*> InterfaceList;