I have a native C++ method, from external unchangable DLL, that expects a std::vector as a argument with 2 native objects. (for example sake, it's an image library returning width/height of a 2 images)
I would like the native objects in the std::vector to be referenced in my own wrapped MyManagedImageObj.
Somehow the std::vector seems to copy values and has no way to add pointers (correct?); so after calling the NativeMethod; I need to copy the properties (width/height) back again to MyManagedImageObj.
I thought about first declaring the std::vec and getting the pointer of the results and put that in MyManagedImageObj as a pointer. But if I understand it correctly std::vector will clean that native memory up once out of scope. (my c++ experience is 1 week; c# long time)
Is there a better way to do this without reassigning the properties one by one?
Ej
The code looks like this:
//create managed object that wraps also native pointer.
MyManagedImageObj^ obj1 = gcnew MyManagedImageObj();
MyManagedImageObj^ obj2 = gcnew MyManagedImageObj();
//keep list of result
List<MyManagedImageObj^>^ resultList;
resultList->Add(obj1);
resultList->Add(obj2);
//call to native method. Dereference pointers of native wrapped objects... not working?
std::vector<DLLNativeImageObj> nativeImageVec { *obj1->GetInstance(), *obj2->GetInstance() };
bool result = otherNativePtr->NativeMethod(nativeImageVec);
//we still need copy it over results now to 'our' managed objects.
int i = 0;
for (DLLNativeImageObj c : nativeImageVec)
{
resultList[i]->ImageHeight = c.imageHeight;
resultList[i]->ImageWidth = c.imageWidth;
++i;
}
The MyManagedImageObj class looks like this:
//MyManagedImageObj.h
public ref class MyManagedImageObj
{
protected:
DLLNativeImageObj* m_Instance;
public:
MyManagedImageObj(DLLNativeImageObj* instance)
: m_Instance(instance)
{
};
~MyManagedImageObj() //destructor will be called whenever we do 'delete'
{
if (m_Instance != nullptr)
{
delete m_Instance;
}
}
!MyManagedImageObj() //finalizer, called by the garbage collector when it's destroys the wrapper object. So safety check to dispose unmanaged item.
{
if (m_Instance != nullptr)
{
delete m_Instance;
}
}
DLLNativeImageObj* GetInstance() //return the pointer to the unmanaged object
{
return m_Instance;
}
property uint32_t ImageWidth
{
public:
uint32_t get()
{
return m_Instance->imageWidth;
}
public:
void set(uint32_t value)
{
m_Instance->imageWidth = value;
}
}
property uint32_t ImageHeight
{
public:
uint32_t get()
{
return m_Instance->imageHeight;
}
public:
void set(uint32_t value)
{
m_Instance->imageHeight = value;
}
}
};
//MyManagedImageObj.cpp
MyManagedImageObj::MyManagedImageObj(new DLLNativeImageObj())
{
// new keyword important: it returns a pointer to the location and does not get deleted when out of scope. Manual delete is required.
}
I created a local server (EXE) COM project with support for ConnectionPoint events.
idl pseudo:
interface IAtlClass : IDispatch{
[id(1)] HRESULT f1();
};
library ComExeLib
{
dispinterface _IAtlClassEvents
{
methods:
[id(1)] HRESULT f2();
};
[
uuid(...
]
coclass AtlClass
{
[default] interface IAtlClass;
[default, source] dispinterface _IAtlClassEvents;
};
};
Server is built in 32 bit configuration. Client code, built in 64 bit:
HRESULT hr = CoInitialize(NULL);
IAtlClass* atlClass;
hr = CoCreateInstance(CLSID_AtlClass, NULL,
CLSCTX_LOCAL_SERVER,
IID_IAtlClass,
reinterpret_cast<void**>(&atlClass));
hr = atlClass->f1();
IConnectionPointContainer* pICPC = NULL;
hr = atlClass->QueryInterface(IID_IConnectionPointContainer, (VOID **)&pICPC);
IConnectionPoint* pICP = NULL;
hr = pICPC->FindConnectionPoint(DIID__IAtlClassEvents, &pICP);
hr = pICP->Advise((_IAtlClassEvents*)&sink, &cookie);
Sink class:
class Sink : public _IAtlClassEvents
{
public:
HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{
if ((DIID__IAtlClassEvents == riid))
{
*ppvObject = static_cast<_IAtlClassEvents*>(this);
AddRef();
return(S_OK);
}
*ppvObject = NULL;
return(E_NOINTERFACE);
}
ULONG STDMETHODCALLTYPE AddRef(void)
{
return(InterlockedIncrement(&m_iRef));
}
ULONG STDMETHODCALLTYPE Release(void)
{
if (0 == InterlockedDecrement(&m_iRef))
{
delete this;
return(0);
}
return(m_iRef);
}
HRESULT STDMETHODCALLTYPE GetTypeInfoCount()
HRESULT STDMETHODCALLTYPE GetTypeInfo()
HRESULT STDMETHODCALLTYPE GetIDsOfNames()
HRESULT STDMETHODCALLTYPE Invoke()
};
Registered the server with ComExe.exe /RegServer and the proxy with regsvr32 ComExePS.dll, under folder C:\windows\SysWOW\ and under c:\Windows\System32.
Not sure if necessary but tried to compile the proxy stub under 64 bit as well but it will not build since auto-generated ComExe_p.c contains an #if !defined(AMD64).. so the project can only be built in 32 bit (seems related to this post only I use VS2013).
All client code commands except the last (Advise) succeed (They succeed even without registering the ComExePS.dll) . Advise invokes the sink QueryInterface method (and none but it), five time with following iid's:
{00000003-0000-0000-C000-000000000046}
{ECC8691B-C1DB-4DC0-855E-65F6C551AF49}
{00000003-0000-0000-C000-000000000046}
{0000001B-0000-0000-C000-000000000046}
{IID_IUnknown}
None of which are related to IAtlClass (some standard MS iid's - this guy was getting something similar).
Eventually Advise returns E_UNEXPECTED Catastrophic failure and the question is what am I doing wrong?
I have a large solution with 50+ unmanaged projects in it. I have recently added a project with managed code in it to the solution. The managed code accesses Windows.Devices.Sensors in a .NET dll. This dll is eventually wrapped by unmanaged code and called from another unmanaged project.
My problem is that I get the following access violation before main() even executes.
Unhandled exception at 0x744b8ea0 in myApplication.exe: 0xC0000005: Access violation.
Managed code:
#using <Windows.winmd>
using namespace Windows::Devices::Sensors;
#include <math.h>
namespace TabletSensors
{
namespace NET
{
public ref class DotNetDllClass
{
public:
DotNetDllClass()
{
Initialization();
}
~DotNetDllClass()
{
}
float* GetQuaternion()
{
OrientationSensorReading^ reading = _orientation->GetCurrentReading();
if( reading != nullptr )
{
float* quat = new float[4];
quat[0] = reading->Quaternion->X;
quat[1] = reading->Quaternion->Y;
quat[2] = reading->Quaternion->Z;
quat[3] = reading->Quaternion->W;
return quat;
}
else
{
return NULL;
}
}
private:
void Initialization()
{
_orientation = OrientationSensor::GetDefault();
if( _orientation != nullptr )
{
_orientation->ReportInterval = 16;
}
else
{
// not good ... throw exception or something
}
}
OrientationSensor^ _orientation;
};
}
}
Wrapper header file:
namespace TabletSensors
{
namespace NETWrapper
{
class DLLEXPORT_SENSORS WrapperClass
{
public:
__stdcall WrapperClass();
__stdcall ~WrapperClass();
float* __stdcall GetQuaternion();
};
}
}
Wrapper cpp file:
#define MIXSENSORS_BUILD
#include <gcroot.h>
#include "DotNetWrapper.h"
#include "DotNetDll.h"
using namespace TabletSensors::NETWrapper;
using namespace TabletSensors::NET;
static gcroot<TabletSensors::NET::DotNetDllClass^> Sensors = nullptr;
static System::UInt16 refCount = 0;
#pragma managed
inline TabletSensors::NET::DotNetDllClass^ GetSensors(void)
{
return (TabletSensors::NET::DotNetDllClass^)Sensors;
}
void Init()
{
++refCount;
if(GetSensors() == nullptr)
{
Sensors = gcnew TabletSensors::NET::DotNetDllClass();
}
}
void CleanUp()
{
if( refCount > 0 )
{
--refCount;
}
}
float* GetQuaternion_()
{
return Sensors->GetQuaternion();
}
#pragma unmanaged
TabletSensors::NETWrapper::WrapperClass::WrapperClass()
{
Init();
}
TabletSensors::NETWrapper::WrapperClass::~WrapperClass()
{
CleanUp();
}
float* TabletSensors::NETWrapper::WrapperClass::GetQuaternion()
{
float* x = new float[4];
return GetQuaternion_();
}
#pragma managed
Unmanaged project referencing my wrapper class:
#include "DotNetWrapper.h"
.
.
.
void UnmanagedProject::Update()
{
// if this line is present, I get an access violation without hitting any breakpoints.
TabletSensors::NETWrapper::WrapperClass _tabletSensors;
.
.
.
}
Since the managed code is trying to access Tablet Sensors I understand why it doesn't work on my Windows 7 desktop. What I don't understand it why it won't even allow me to debug my code at all. No breakpoints are hit before the Access Violation occurs.
What I would really like to figure out is how to use exception handling or #ifdefs to keep this crash from happening. But I have had very little luck.
Any ideas?
The fix is to Delay Load the managed DLL. The allows the application to run until that DLL is explicitly called. Thanks to Ben Voight for his answer here: https://stackoverflow.com/a/28467701/1454861
I have this code for the C# in Visual Studio 2012.
public Task SwitchLaserAsync(bool on)
{
return Task.Run(new Action(() => SwitchLaser(on)));
}
This will execute SwitchLaser method (public nonstatic member of a class MyClass) as a task with argument bool on.
I would like to do something similar in managed C++/CLI. But I am not able to find out any way how to run a task, which will execute a member method taking one parameter.
Current solution is like this:
Task^ MyClass::SwitchLaserAsync( bool on )
{
laserOn = on; //member bool
return Task::Run(gcnew Action(this, &MyClass::SwitchLaserHelper));
}
Implementation of SwitchLaserHelper function:
void MyClass::SwitchLaserHelper()
{
SwitchLaser(laserOn);
}
There must be some solution like in C# and not to create helper functions and members (this is not threadsafe).
There isn't yet any way to do this.
In C# you have a closure. When your C++/CLI compiler was written, the standardized syntax for closures in C++ was still being discussed. Thankfully, Microsoft chose to wait and use the standard lambda syntax instead of introducing yet another unique syntax. Unfortunately, it means the feature isn't yet available. When it is, it will look something like:
gcnew Action([this, on](){ SwitchLaser(on) });
The current threadsafe solution is to do what the C# compiler does -- put the helper function and data members not into the current class, but into a nested subtype. Of course you'll need to save the this pointer in addition to your local variable.
ref class MyClass::SwitchLaserHelper
{
bool laserOn;
MyClass^ owner;
public:
SwitchLaserHelper(MyClass^ realThis, bool on) : owner(realThis), laserOn(on) {}
void DoIt() { owner->SwitchLaser(laserOn); }
};
Task^ MyClass::SwitchLaserAsync( bool on )
{
return Task::Run(gcnew Action(gcnew SwitchLaserHelper(this, on), &MyClass::SwitchLaserHelper::DoIt));
}
The C++ lamdba syntax will simply create that helper class for you (currently it works for native lambdas, but not yet for managed ones).
Here's generic code I wrote this afternoon which might help (although it's not an exact match for this question). Maybe this will help the next person who stumbles onto this question.
generic<typename T, typename TResult>
ref class Bind1
{
initonly T arg;
Func<T, TResult>^ const f;
TResult _() { return f(arg); }
public:
initonly Func<TResult>^ binder;
Bind1(Func<T, TResult>^ f, T arg) : f(f), arg(arg) {
binder = gcnew Func<TResult>(this, &Bind1::_);
}
};
ref class Binder abstract sealed // static
{
public:
generic<typename T, typename TResult>
static Func<TResult>^ Create(Func<T, TResult>^ f, T arg) {
return (gcnew Bind1<T, TResult>(f, arg))->binder;
}
};
Usage is
const auto f = gcnew Func<T, TResult>(this, &MyClass::MyMethod);
return Task::Run(Binder::Create(f, arg));
Here's the working answer.. Have tested it.. Passing an argument (int) to the action sampleFunction.
#include "stdafx.h"
#include "CLRSamples.h"
using namespace System;
using namespace System::Threading;
using namespace System::Threading::Tasks;
using namespace System::Collections;
using namespace System::Collections::Generic;
void CLRSamples::sampleFunction(Object^ number)
{
Console::WriteLine(number->ToString());
Thread::Sleep((int)number * 100);
}
void CLRSamples::testTasks()
{
List<Task^>^ tasks = gcnew List<Task^>();
for (int i = 0; i < 10; i++)
{
tasks->Add(Task::Factory->StartNew((Action<Object^>^)(gcnew Action<Object^>(this, &CLRSamples::sampleFunction)), i));
}
Task::WaitAll(tasks->ToArray());
Console::WriteLine("Completed...");
}
int main(array<System::String ^> ^args)
{
CLRSamples^ samples = gcnew CLRSamples();
samples->testTasks();
Console::Read();
return 0;
}
I had a similar problem when I wanted to provide a parameter to a task executing a method which does not return a value (retuns void). Because of that Func<T, TResult> was not an option I could use. For more information, please check the page Using void return types with new Func.
So I ended up with a solution where I created a helper class
template <typename T>
ref class ActionArguments
{
public:
ActionArguments(Action<T>^ func, T args) : m_func(func), m_args(args) {};
void operator()() { m_func(m_args); };
private:
Action<T>^ m_func;
T m_args;
};
which is using Action<T> delegate to encapsulate a method that has a single parameter and does not return a value.
I would then use this helper class in a following way
ref class DisplayActivationController
{
public:
DisplayActivationController();
void StatusChanged(EventArgs^ args) { };
}
Action<EventArgs^>^ action =
gcnew Action<EventArgs^>(this, &DisplayActivationController::StatusChanged);
ActionArguments<EventArgs^>^ action_args =
gcnew ActionArguments<EventArgs^>(action, args);
Threading::Tasks::Task::Factory->
StartNew(gcnew Action(action_args, &ActionArguments<EventArgs^>::operator()));
Approach using the helper class is probably not the most elegant solution, but is the best one I could find to be used in C++/CLI which does not support lambda expressions.
If you are using c++/ CLR, then make a C# dll and add reference to it
namespace TaskClrHelper
{
public static class TaskHelper
{
public static Task<TResult> StartNew<T1, TResult>(
Func<T1, TResult> func,
T1 arg)
=> Task.Factory.StartNew(() => func(arg));
public static Task<TResult> StartNew<T1, T2, TResult>(
Func<T1, T2, TResult> func,
T1 arg1, T2 arg2)
=> Task.Factory.StartNew(() => func(arg1, arg2));
}
}
bool Device::Stop(int timeout)
{
_ResetEvent_Running->Set();
return _ResetEvent_Disconnect->WaitOne(timeout);
}
Task<bool>^ Device::StopAsync(int timeout)
{
auto func = gcnew Func<int, bool>(this, &Device::Stop);
return TaskClrHelper::TaskHelper::StartNew<int,bool>(func,timeout);
}
How to get the properties of an interface within the type library the interface is defined, Keeps returning HRESULT but would like it to return the actual value of the property.
EDIT:
IDL:
interface IMyClassInterface : IDispatch
{
[propget, id(1), helpstring("Gets user Type")] HRESULT getUserDefineTypeVal([out,retval] UserDefineEnum *ptrVal);
[propput, id(1), helpstring("Sets user Type ")]HRESULT setUserDefineTypeVal([in] UserDefineEnum newVal);
}
Property in Header File:
STDMETHOD(getUserDefineTypeVal)(UserDefineEnum *ptrVal);
STDMETHOD(setUserDefineTypeVal)(UserDefineEnum newVal);
Property in MYClass.cpp:
STDMETHODIMP CMYClass::getUserDefineTypeVal(UserDefineEnum *ptrVal) {
*ptrVal = UserDefineEnum(private_var_UserDefineTypeVal);
return S_OK;
}
AnotherClass within the Type Library:
IMyClassInterface* private_var_MyClass
STDMETHODIMP CAnotherClass::someMethod(){
UserDefineEnum* p;
if(private_var_MyClass->getUserDefineTypeVal(p)){
//do somestuff
}
}
The problem is the if condition doesn’t return true. However the below partially works.
HRESULT hr = private_var_MyClass->getUserDefineTypeVal(p);
if(hr == S_OK){ do somestuff }
The problem with this is if I attempt a case statement the only value in hr is 0. I need to check the value being set on the clientside.
The value of S_OK is 0, that's why your if() statement doesn't execute. You should use the SUCCEEDED macro:
UserDefinedEnum value;
HRESULT hr = private_var_MyClass->getUserDefineTypeVal(&value);
if (SUCCEEDED(hr)) {
switch (value) {
// etc...
}
}
else {
// do something with the error...
}
COM usually uses out parameters to return values. In C/C++ you have to pass a pointer to a variable which will contain the result upon return.
The HRESULT return parameter is only used to report the success (or failure) of the method call.
EDIT For your code, you need to reserve the memory for the result by the caller:
UserDefineEnum p; // No * here ...
if (private_var_MyClass->getUserDefineTypeValue(&p) == S_OK) { // note '&' operator!
switch (p) {
case ENUM_1: // ...
case ENUM_2:
// ...
}
}