How to call a native method with a std::vector as argument and retrieve the native object in wrapped class - c++-cli

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.
}

Related

Assigning QObject pointer works via assignment but not binding

I have something similar to the following code snippets. I am simplifying the code here for attempted brevity.
First, a subclass of QAbstractListModel with the following data() implementation, and Q_INVOKABLE get_thing() method, which returns a pointer to a QObject subclass, QML_thing:
QVariant data(QModelIndex& index, int role) {
const auto& thing = m_data.at(index.row()); // shared pointer to QML_thing
switch(role)
{
case Qt::DisplayRole:
return thing->name(); // this works
case WholeThingRole:
return QVariant::fromValue(QML_thing*>(thing.get());
}
}
QML_thing* getThing(int index) const
{
const thing = m_data.at(index); // shared pointer
return thing.get();
}
Next, I have a Repeater in a QML file that has this code:
Repeater {
id: repeater
model: thingModel
ThingDelegate {
thing: wholeThing // This calls the role, but ends up being null
}
onItemAdded {
item.thing = model.getThing(index) // this works, but 'breaks' the binding
}
}
My question is: why doesn't the thing: binding in QML work, but the thing = version does?

RunmtimeTypeHandle to type

Here is a sample program that wraps up a managed enum for unmanaged use. I want to be able to get wrapped enums back from unmanaged code and convert them back to managed enums with as little overhead as possible. My current scheme requires creating a GCHandle to the Type object. I was thinking maybe there is a way to use the RuntimeTypeHandle value instead to remove this overhead. Is that possible? Or any other efficiency suggestions anyone has.
public value class Stuff {
public:
enum class Modes { A, B };
};
struct enum_wrap {
intptr_t type;
int value;
};
void g(enum_wrap e);
enum_wrap h();
void f(Stuff::Modes mode)
{
enum_wrap wrap;
wrap.value = (int)mode;
wrap.type = static_cast<intptr_t>(GCHandle::ToIntPtr(GCHandle::Alloc(Stuff::Modes::typeid)));
g(wrap);
// ...
enum_wrap ret = h();
Type^ ret_type = safe_cast<Type^>(GCHandle::FromIntPtr(static_cast<IntPtr>(ret.type)).Target);
Enum^ e_obj = (Enum^)Enum::ToObject(ret_type, ret.value);
Console::Write(e_obj->GetType());
Console::Write(": ");
Console::WriteLine(e_obj);
}
#pragma unmanaged
enum_wrap g_enum;
void g(enum_wrap e) {
g_enum = e;
}
enum_wrap h() {
return g_enum;
}
I know this leaks because of never freeing GCHandles. I already have code that can deal with that if this is the best approach I can find. But I'm hoping to not need the Type objects at all.
Edit 1: Put Modes enum in a class so it works right.

How to create a static pointer variable to itself in Swift?

In Objective-C I often use the pattern of using a static void* as an identification tag. At times these tags are only used within that function/method, hence it's convenient to place the variable inside the function.
For example:
MyObscureObject* GetSomeObscureProperty(id obj) {
static void* const ObscurePropertyTag = &ObscurePropertyTag;
MyObscureObject* propValue = objc_getAssociatedObject(id,ObscurePropertyTag);
if(!propValue) {
propValue = ... // lazy-instantiate property
objc_setAssociatedObject(obj,ObscurePropertyTag,propValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return propValue;
}
The question is, how to write the ObscurePropertyTag private-constant-pointer-to-itself in Swift? (Preferrably 2.1 but future already-announced versions should be okay)
I've looked around and it seems that I have to put this ObscurePropertyTag as a member variable and there doesn't seem to be a way around it.
Unlike (Objective-)C, you cannot take the address of an
uninitialized variable in Swift. Therefore creating a self-referencing
pointer is a two-step process:
Swift 2:
var ptr : UnsafePointer<Void> = nil
withUnsafeMutablePointer(&ptr) { $0.memory = UnsafePointer($0) }
Swift 3:
var ptr = UnsafeRawPointer(bitPattern: 1)!
ptr = withUnsafePointer(to: &ptr) { UnsafeRawPointer($0) }
For your purpose, is it easier to use the address of a global variable with &, see for
example
Is there a way to set associated objects in Swift?.
If you want to restrict the scope of the "tag" to the function itself
then you can use a static variable inside a local struct. Example:
func obscureProperty(obj : AnyObject) -> MyObscureObject {
struct Tag {
static var ObscurePropertyTag : Int = 0
}
if let propValue = objc_getAssociatedObject(obj, &Tag.ObscurePropertyTag) as? MyObscureObject {
return propValue
}
let propValue = ... // lazy instantiate property value
objc_setAssociatedObject(obj, &Tag.ObscurePropertyTag,propValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return propValue
}
Try this:
var GetSomeObscureProperty: MyObscureObject = nil
withUnsafePointer(& GetSomeObscureProperty) {
GetSomeObscureProperty = MyObscureObject($0)
}
In short
let GetSomeObscureProperty = UnsafePointer<()>()

Type casting in C++\CLI project

I have project which I am compiling with /clr. I have a class like below..
ref class A
{
public:
void CheckValue(void * test);
typedef ref struct val
{
std::string *x;
}val_t;
};
in my implementation I ahve to use something like below..
void A::CheckValue(void *test)
{
a::val_t^ allVal = (a::val_t^)test;
}
in my main I have used like..
int main()
{
A^ obj = gcnew A();
a::val_t valObj = new std::string("Test");
obj->CheckValue((void*)valObj);
}
I am getting type cast error and two places -
obj->CheckValue((void*)valObj);
and at
obj->CheckValue((void*)valObj);
error C2440: 'type cast' : cannot convert from 'void*' to 'A::val_t ^'
This snippet is just to show behavior at my end and I ahve to use it this way only. Earlier I was running it using non /clr so it compiled fine.
Now question I have how can I make this type casting work in C++/CLI type project?
Replace void * with Object^. You can also write a generic version of CheckValue but then there is not much point of having a weak-typed parameter when you have the type in the generic parameter.
A reference handle represents an object on the managed heap. Unlike a native pointer, CLR could move the object around during a function call, so the behavior of a pointer and a reference handle is different, and a type cast would fail. You can also pin the object being referenced using pin_ptr if you really need a void* so CLR would not be moving the object during the function call.
Here is how I would get around the limitation you are seeing, just remove the struct from the managed object, since it contains native pointer types.
struct val_t
{
char* x;
};
ref class A
{
public:
void CheckValue(void* test);
};
void A::CheckValue(void* test)
{
val_t* allVal = (val_t*)test;
}
int main()
{
A^ obj = gcnew A();
val_t valObj;
valObj.x = "Test";
obj->CheckValue((void*)&valObj);
}
Now, if you absolutely need the struct to be managed, here is how to do it:
ref class A
{
public:
void CheckValue(void * test);
value struct val_t
{
char* x;
};
};
void A::CheckValue(void *test)
{
a::val_t* allVal = (a::val_t*)test;
}
int main()
{
A^ obj = gcnew A();
a::val_t valObj;
valObj.x = "Test";
pin_ptr<a::val_t> valPin = &valObj;
obj->CheckValue((void*)valPin);
}

C++/CLI: Passing C++ class ptr to unmanaged method

I've been given a third party C/C++ library (.dll, .lib, .exp and .h) that I need to use in our C# app.
ThirdPartyLibrary.h contains...
class AClass {
public:
typedef enum {
green = 7,
blue = 16
} Color;
virtual int GetData()=0;
virtual int DoWork(Color, char *)=0;
};
void * Func1(int, AClass **aClass);
In my C++/CLI code I have done this...
#include "ThirdPartyLibrary.h"
using namespace System;
using namespace System::Runtime::InteropServices;
namespace Wrapper {
public ref class MyBridgeClass
{
private:
AClass* pAClass;
public:
// C# code will call this method
void AMethod (int x)
{
int y = x+10;
Func1 (y, &(this->pAClass)); // <-- error!
}
}
}
I get a build error that reads...
cannot convert parameter 2 from 'cli::interior_ptr<Type>' to 'AClass **'
with
[
Type=AClass *
]
Cannot convert a managed type to an unmanaged type
Any ideas? Maybe I need #pragma manage/unmanged tags in my C++/CLI?
The reason you're getting that error is because of how managed memory works.
In your managed class, you've got a pointer defined. The address of that pointer is part of the managed object, and can change when the garbage collector runs. That's why you can't just pass &pAClass to the method, the GC can change what that address actually is.
There's a couple things you can do to fix this:
You could create an unmanaged helper class to hold the AClass* member. I'd do this if that pointer needs to stay valid beyond the invocation of this method, or if you have a lot of unmanaged pointers to hold.
struct UnmanagedHolder
{
AClass* pAClass;
};
public ref class MyBridgeClass
{
private:
// must create in constructor, delete in destructor and finalizer.
UnmanagedHolder* unmanaged;
public:
// C# code will call this method
void AMethod (int x)
{
int y = x+10;
Func1 (y, &(this->unmanaged->pAClass));
}
};
If you only need the pointer to be valid within AMethod, and the pointer doesn't need to remain valid after the call to Func1, then you can use a pin_ptr.
void AMethod (int x)
{
int y = x+10;
pin_ptr<AClass*> pin = &(this->pAClass);
Func1 (y, pin);
}