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?
Related
I am inexperienced with C++, so I might be missing the correct search terms.
I want to replace a few library functions with my own wrappers at runtime. Basically, I would like to provide an instrumented version of the library. In an ideal world, users of the library would not have to alter their code to use this version (or, at most, change only the linking within CMakeLists.txt).
User-defined executables are often declared as follows in a CMake file.
add_library(my_code ${SOURCES})
add_dependencies(my_code ${catkin_EXPORTED_TARGETS})
target_link_libraries(my_code ${catkin_LIBRARIES})
I suppose that, to achieve this, changing target_link_libraries() would be required, so as to link to a different version.
However, even if I redefine all functions in the original header, under the same namespace, how can I refer to the original implementation?
namespace thelib {
void theFunction() {
// how do I call the original thelib::theFunction() here?
}
}
Basically it is to good practice to isolate third party dependency using come abstraction. Aim is to hide library API behind some interface, which implementation an be freely altered.
I do it more or less that:
// some header
class IDependency {
public:
virtual ~IDependency() = default;
virtual void theFunction() = 0;
};
std::unique_ptr<IDependency> depFactory(int someArg);
// some cpp
std::unique_ptr<IDependency> depFactory(int someArg)
{
if (someArg = 0) {
return std::make_unique<LibraryWrapper>();
}
if (someArg = 0) {
auto origLib = std::make_unique<LibraryWrapper>();
return std::make_unique<DepCutomization>(origLib);
}
throw std::invalid_argument("");
}
// LibraryWrapper
class LibraryWrapper : public IDependency {
public:
void theFunction() override {
::thelib::theFunction();
}
}
// DepCutomization
class DepCutomization : public IDependency {
public:
explicit DepCutomization(std::unique_ptr<IDependency> orig)
: m_orig(std::move(orig))
{}
void theFunction() override {
customAction();
m_orig->theFunction();
}
void customAction()
{}
private:
std::unique_ptr<IDependency> m_orig;
};
For cases where performance is important, I'm using static polymorphism (template programing).
I'm currently working on a game engine which implements an architecture based on frameworks.
These frameworks are dynamically loaded into the engine through the using of .so libraries.
To illustrate the frameworks usage, here is a little picture:
Engine/Frameworks interactions
(please, note that the engine also knows about the FrameworkTpl and SpecificFrameworkTpl types)
As we can see, the specificFrameworkImplementation class is compiled as a shared library (.so) and inherit from specificFrameworkTpl which itself inherit from FrameworkTpl.
Once compiled, the library is loaded into the engine at runtime and an instance of the framework is retrieved as a FrameworkTpl.
At this time if I call a FrameworkTpl method, it will works like a charm (which is pretty obvious yes...).
Neverless, if I try to down cast this instance to a specificFrameworkTpl with the help of a dynamic_cast, it will return a nullptr.
Through my research (which have last for about one week while reading mans pages and StackOverflow answers), I saw peoples talking about flags to give to the dlopen function such as RTLD_NOW or to remove like RTLD_LOCAL in favor of RTLD_GLOBAL, but none of them has worked for me, same thing for g++ flags (-rdynamic).
The code:
Here is an example with GuiFrameworkTpl as specificFrameworkTpl
and FrameworkUI for specificFrameworkImplementation.
FrameworkTpl
class FrameworkTpl
{
protected:
std::string _name;
public:
FrameworkTpl(const std::string &name):
_name(name)
{
}
virtual ~FrameworkTpl(void)
{
}
public:
virtual std::string getName(void) const
{
return (this->_name);
}
};
GuiFrameworkTpl
class GuiFrameworkTpl : public FrameworkTpl
{
public:
GuiFrameworkTpl(const std::string & name) :
FrameworkTpl(name)
{
}
virtual ~GuiFrameworkTpl(void)
{
}
virtual void displaySquare(int x, int y, int size) = 0;
};
FrameworkUI
class FrameworkUI : public GuiFrameworkTpl
{
public:
FrameworkUI();
~FrameworkUI();
public:
void displaySquare(int x, int y, int size);
};
extern "C"
{
FrameworkUI* CObject()
{
return (new FrameworkUI);
}
void DObject(FrameworkUI* obj)
{
delete obj;
}
}
App that uses the library and cast stuff from it:
(Here, the Xxx from the previous classes is used as "Gui")
GuiFrameworkTpl* GUISystem::cast_f(const std::shared_ptr<FrameworkTpl>& src)
{
auto ptr = src.get();
Log::print(ptr);
if (!ptr) return nullptr;
Log::inform(ptr->getName());
auto dst = dynamic_cast<GuiFrameworkTpl*>(ptr);
Log::print(dst);
return dst;
}
What I should have:
When I load my library and call CObject() it should create an instance of FrameworkUI which I get in a FrameworkTpl, then I would just have to dynamic_cast it as a GuiFrameworkTpl in order to access particular method.
What I really have:
When I load my library and call CObject() it creates an instance of FrameworkUI which I store in a FrameworkTpl (btw, I can call the getName() method successfully, so the instance is valid). But when I try to down cast it to GuiFrameworkTpl, it gives me a nullptr.
The last function print this:
0xc0c200
[INFO]: FrameworkUI
0
If anyone has some clue about how to solve this problem, I would be very grateful,
Thanks in advance
I'm trying to make platform independent code so I'm using OOP. For example, on Windows, Mac OS X, and Linux you can have windows, but on android you have views so I'm trying to abstract this.
I first made a class to represent a window or a view which I called view:
class View
{
public:
virtual ~View()
{}
virtual void display() = 0;
virtual void hide() = 0;
};
Now the problem is that on Android, there is no title for views while on Windows there are so I decided to create another class:
class NameableView : public View
{
public:
virtual void setName(const std::string& name)
};
And then finally implement the classes:
class WindowsView : public NameableView
{
/* Windows implementation */
}
class AndroidView : public View
{
/* Android implementation */
}
Then I need to make some code which sets the name for a view only if it is possible (if it inherits from the NameableView class).
So how can I solve this problem? I first thought about dynamic_cast but I often hear that having too much dynamic_cast is an indication of a design problem. I'm a beginner in C++ so maybe I didn't think the right way and I should change the whole design.
I'm trying to make platform independent code so I'm using OOP.
This is not an optimal approach - polymorphic hierarchies and virtual functions allow different concrete object types that inherit from the same interface to behave differently at run-time, but you know the platform you're going to target at compile-time.
What you should instead do is use static polymorphism and CRTP to provide a common interface that every concrete per-platform implementation must satisfy.
template <typename TDerived>
struct View
{
void display() { static_cast<TDerived&>(*this).display(); }
void hide() { static_cast<TDerived&>(*this).hide(); }
constexpr bool supportsSetView() const
{
return static_cast<TDerived&>(*this).supportsSetView();
}
};
In the case of setName, you should provide a supportsSetView check on every platform that returns true at compile-time if the view can be named. Then you perform that check on the caller side and only invoke setName if the check passes.
Example usage:
#if defined(PLATFORM_ANDROID)
struct AndroidView
{
// ...
constexpr bool supportsSetView() const { return false; }
};
using MyView = View<AndroidView>;
#else if defined(PLATFORM_WINDOWS)
struct WindowsView
{
// ...
constexpr bool supportsSetView() const { return true; }
void setName(std::string x) { /* ... */ }
};
using MyView = View<WindowsView>;
#else
#error "Unsupported platform."
#endif
Caller side:
MyView currentView;
if constexpr(currentView.supportsSetView())
{
currentView.setName("something");
}
As if constexpr(...)'s evaluation occurs at compile-time, the code will only call setName if it is supported by MyView.
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.
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