How to properly create a property to store any amount of values? - visual-c++

Making the shift from C++ to C++/CX I stumbled upon that ref classes can't have native members in they're public or protected members, due to possible errors with java and stuff. Instead we now have to use properties, which I can make but only to hold 1 value...
The idea was to make a property that would store 4 floats in an array or vector and later pass the values to a XMVECTOR. The relevant code I have in the class header file until now is:
public:
property std::vector<float> num{
void set(std::vector<float> e){
NUM = e;
};
std::vector<float> get(){
return NUM;
};
};
private:
std::vector<float> NUM;
Later in the .cpp file I do:
std::vector<float> g;
g.pushback(3);
num = g;
I also make it a string to pass to a TextBox(but that's not important). In the end I just get many similar errors... The 2 errors are:
error C3986: 'set': signature of public member contains native type 'std::vector<_Ty>'
error C3986: 'set': signature of public member contains native type 'std::allocator<_Ty>'
The only thing I imagine is that I can't use strings or vectors. I know Platform::Strings exist but what about vectors??

Standard C++ types cannot be projected across the WinRT ABI, which is the communication layer shared by all WinRT language projections (C#/VB/JS). As Jagannath mentions, there is a collection interface (Windows::Foundation::Collections::IVector<T>). There is also a dictionary type (IMap<K,V>) and various iterators and support types. These are understood by all languages, but are just interfaces. Each language projection is responsible for authoring runtime classes that implement these interfaces. For C++/Cx, these ref classes are found in the header <collection.h> and are in the namespace Platform::Collections. Platform::Collections::Vector<T> and Platform::Collections::Map<K,V> are the basic types you can use as backing stores. Additionally, Vector<T> can be move-constructed from std::vector<T>.
However, you can't make a public property of type Platform::Collections::Vector<T> either, as this is still a C++ type. What you do instead is create a public property of type Windows::Foundation::Collection::IVector<T> which is backed by a private member variable of type Platform::Collections::Vector<T>.
Essentially:
public:
property Windows::Foundation::Collections::IVector<float>^ num{
Windows::Foundation::Collections::IVector<float>^ get(){
return NUM;
}
}
private:
Platform::Collections::Vector<float>^ NUM;
I have avoided mentioning the property setter, because that gets tricky (your private type would need to also be an IVector and it will only be a Platform::Collections::Vector if it came from C++).

You could use Windows::Foundation::Collections::IVector<float>^ for the signatures. I could not test this as I don't have the compiler at hand.

Hey guys I managed to get this working so I thought I'll post the code. The header file goes like this:
public:
property Windows::Foundation::Collections::IVector<int>^ num{
void set(Windows::Foundation::Collections::IVector<int>^ e){
NUM = safe_cast<Platform::Collections::Vector<int>^>(e);
};
Windows::Foundation::Collections::IVector<int>^ get(){
return NUM;
};
};
private:
Platform::Collections::Vector<int>^ NUM;
And in the .cpp file the code is:
num = ref new Vector<int>;
num->Append(5);
num->Append(54);
TextBox1->Text = num->GetAt(0).ToString() + "\n" + num->GetAt(1).ToString();
The result will have written the values 5 and 54 to a TextBox.

Related

Can a managed ref-class directly implement a COM interface?

Is there a built-in way to allow a managed ref-class to implement and expose a COM inerface that is safely callable from native code?
Looking at the C# side, this is easily done by decorating the target interface with the proper COM-interop attributes, for example:
Native Interface
interface ISampleGrabberCB: public IUnknown
{
virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ) = 0;
virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ) = 0;
};
static const IID IID_ISampleGrabberCB = { 0x0579154A, 0x2B53, 0x4994,
{ 0xB0, 0xD0, 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85 } };
Managed Equivalent Interface
[Guid("0579154A-2B53-4994-B0D0-E773148EFF85")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[SuppressUnmanagedCodeSecurity]
public interface ISampleGrabberCB {
int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen);
int SampleCB(double SampleTime, IMediaSample pSample);
}
Once this declaration is done, through the magic of P-Invoke you can do something like this:
public class FooClass : ISampleGrabberCB {
int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen) {
Console.WriteLine("BufferCB called");
}
int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample pSample) {
Console.WriteLine("SampleCB called");
}
public void SomeMethod(IBaseFilter aDirectShowFilter) {
ISampleGrabber sampleGrabber = (ISampleGrabber)aDirectShowFilter;
// By the magic of PInvoke, this is possible and works!
// ISampleGrabber->SetCallback() is expecting an ISampleGrabberCB* COM interface
// After the following line, native code is able to callback safely
// into our managed code
sampleGrabber.SetCallback(this, 0);
}
}
Is there a way to mimic this behavior on C++/CLI?
Evidently, the Interop plumbing to make this possible exists as it is used by C#. Furthermore, the compiler could generate the necessary managed interface from inspecting the available native interfaces (I still think we would need to provide the relevant Guids, as this is not an attribute within the native interface)
I just got curious about this topic and played around and I found out some minor differences:
I have IVI-COM class library on my PC, and always wanted to try to interface some of them, although the IVI also has .Net interfaces so it does not make too much sense...
I started with C#, where we get good IntelliSense support. I have added the necessary references and added a class to my project. With the object browser we can select an interface.
public class MyDmm : IIviDmmMultiPoint
{
}
After that just use IntelliSense (Ctrl-.) to add the ‘using’ statement and let them make the necessary properties and methods for us.
using Ivi.Dmm.Interop;
///...
public int Count
{
get
{
throw new NotImplementedException();
}
///...
So now we need the C++-CLI dialect :) Which is as follows:
using namespace IviDmmLib;
///...
public ref class Dmm : IIviDmmMultiPoint
{
Note that the name used by the using statement is different, we can obtain this by selecting the reference at the Solution Explorer and check the name shown at the ‘Properties’ below.
I did not fully complete the experiment but I saw that the COM library was x64 bit, so we may compile the project for the same.
Further interesting readings:
Windows Runtime C++ Template Library
Please, give me feedback if you find some more differences, so we can put them here too.

QtConcurrent::map() with member function = can not compile

My project is to create a small program which demonstrates the work of a search engine: indexing and returning result for arbitrary queries. I've done the work with the indexer part and now I want to improve it with indexing multiple files at once. The MainWindow class is here:
class MainWindow : public QMainWindow
{
Q_OBJECT
.....
private:
Indexer * indexer;
QStringList fileList;
....
void index(QStringList list);
void add(const QString &filename);
}
This is the implementation of add (add need to access fileList to avoid index the same files again, thus it can not be static method):
void MainWindow::add(const QString &filename)
{
if (!fileList.contains(filename))
{
indexer->addDocument(filename.toStdString());
fileList.append(filename);
qDebug() << "Indexed" << filename;
emit updatedList(fileList);
}
}
The implement of index method is to receive a file lists and call add upon each file name:
void MainWindow::index(QStringList list)
{
....
QtConcurrent::map(list, &MainWindow::add);
....
}
The error I receive when compiling these code is:
usr/include/qt4/QtCore/qtconcurrentmapkernel.h: In member function 'bool QtConcurrent::MapKernel<Iterator, MapFunctor>::runIteration(Iterator, int, void*) [with Iterator = QList<QString>::iterator, MapFunctor = QtConcurrent::MemberFunctionWrapper1<void, MainWindow, const QString&>]':
../search-engine/mainwindow.cpp:361:1: instantiated from here
/usr/include/qt4/QtCore/qtconcurrentmapkernel.h:73:9: error: no match for call to '(QtConcurrent::MemberFunctionWrapper1<void, MainWindow, const QString&>) (QString&)'
/usr/include/qt4/QtCore/qtconcurrentfunctionwrappers.h:128:7: note: candidate is:
/usr/include/qt4/QtCore/qtconcurrentfunctionwrappers.h:138:14: note: T QtConcurrent::MemberFunctionWrapper1<T, C, U>::operator()(C&, U) [with T = void, C = MainWindow, U = const QString&]
/usr/include/qt4/QtCore/qtconcurrentfunctionwrappers.h:138:14: note: candidate expects 2 arguments, 1 provided
I'm not really familiar with how QtConcurrent works, and the documentation doesn't provide much details about it. I really hope that someone here can help. Thanks in advance.
To be able to call a pointer-to-member, you need, in addition to that functions formal arguments, an instance of that class (the this pointer that you get inside member functions).
There are two ways to handle this: create a simple functor to wrap the call, or use a lambda.
The functor would look like this:
struct AddWrapper {
MainWindow *instance;
AddWrapper(MainWindow *w): instance(w) {}
void operator()(QString const& data) {
instance->add(data);
}
};
And you'd use it like:
AddWrapper wrap(this);
QtConcurrent::map(list, wrap);
(Careful with the lifetime of that wrapper though. You could make that more generic - you could also store a pointer-to-member in the wrapper for instance, and/or make it a template if you want to reuse that structure for other types.)
If you have a C++11 compiler with lambdas, you can avoid all that boilerpalte:
QtConcurrent::map(list, [this] (QString const& data) { add(data); });
Note: I'm not sure how QtConcurrent::MemberFunctionWrapper1 got involved in your example, I'm not seeing it here. So there might be a generic wrapper already in Qt for this situation, but I'm not aware of it.

Type parameters - get concrete type from type T : IMyInterface

Suppose I have a List<IMyInterface>...
I have three classes which implement IMyInterface: MyClass1, MyClass2, and MyClass3
I have a readonly Dictionary:
private static readonly Dictionary<Type, Type> DeclarationTypes = new Dictionary<Type, Type>
{
{ typeof(MyClass1), typeof(FunnyClass1) },
{ typeof(MyClass2), typeof(FunnyClass2) },
{ typeof(MyClass3), typeof(FunnyClass3) },
};
I have another interface, IFunnyInteface<T> where T : IMyInterface
I have a method:
public static IFunnyInterface<T> ConvertToFunnyClass<T>(this T node) where T : IMyInterface
{
if (DeclarationTypes.ContainsKey(node.GetType())) {
IFunnyInterface<T> otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node);
return otherClassInstance;
}
return null;
}
I'm trying to call the constructor of FunnyClasses and insert as parameter my MyClass object. I don't want to know which object it is: I just want to instantiate some FunnyClass with MyClass as a parameter.
What happens when I call ConvertToFunnyClass, T is of type IMyInterface, and when I try to cast it to FunnyInterface<T>, it says I can't convert FunnyClass1, for instance, to FunnyInterface<IMyInterface>
My current workaround (not a beautiful one), is this:
public static dynamic ConvertToFunnyClass<T>(this T node) where T : IMyInterface
{
if (DeclarationTypes.ContainsKey(node.GetType())) {
var otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node);
return otherClassInstance;
}
return null;
}
And I don't like it because the return type is dynamic, so when I access it from somewhere else, I have no idea what type it is, and I lose intellisense, and stuff. I don't know about any performance implications either.
Any clues?
Thanks in Advance!
Resolution
As I'm using C# 4.0, I could stop casting errors using covariance (output positions only), and so I changed my IFunnyInterface to
IFunnyInteface<out T> where T : IMyInterface
Thank you all for the replies.
Essentially, your problem is that you are trying to convert FunnyInterface<T> to FunnyInterface<IMyInterface>. As has been mentioned several times (one example is here, more information here), this is not valid in most circumstances. Only in .NET 4, when the generic type is an interface or delegate, and the type parameter has been explicitly declared as variant with in or out, can you perform this conversion.
Is FunnyInterface actually an interface?
thecoop answer points you exactly to why you can't do it.
A cleaner solution to the problem (besides using dynamic) would be a base non-Generics Interface:
public interface IFunnyInterfaceBase
{
}
public interface IFunnyInteface<T> : IFunnyInterfaceBase
where T : IMyInterface
{
}
And you need to move methods signature you use in that code from IFunnyInteface to IFunnyInterfaceBase.
This way you would be able to write something like this:
MyClass2 c2 = new MyClass2();
IFunnyInterfaceBase funnyInstance = c2.ConvertToFunnyClass();
The Exception you said you got in your code is not due to the extension method signature itself (the method is fine)..it is originated by the type of your lvalue (the type of the variable you use to store its return value)!
Obviously this solution applies only if you can modify IFunnyInterface source code!

How to return a vector of objects to managed code efficiently?

I have a ref class that contains a pointer to an unmanaged class. the class has some basic types and also a vector of objects of another class. I would like to know the best way to get and set the vector from managed code. Will a memcpy between unmangedb objects be efficient or setting each member variable of unmanagedb?
for ex (assume the class is complete. I am writing what is relevant to the question)
Assume we already have a managed wrapped for struct UnmanagedB called B.
struct UnmanagedA
{
int a;
vector<UnmanagedB> list;
};
public ref class A : public System::IDisposable
{
public:
// properties
property System::UInt32 a
{
System::UInt32 get();
void set(System::UInt32 value);
}
property array<B^>^ list
{
System::array<B^>^ get(); // what is the best way to set and get the vector
void set(array<B^>^ value);
}
private:
UnmanagedA* obj1;
};
This obviously won't be cleanly possible, since UnmanagedA contains a vector of UnmanagedB values, while A exposes an property of type array<B^>. If this is intended and not a typo, you will need to marshall the content of B^ into instances of UnmanagedB. Otherwise, let UnmanagedA hold a std::vector< B* > and take care of proper lifetime management.

Faking enums in Entity Framework 4.0

There are a lot of workarounds for the missing support of enumerations in the Entity Framework 4.0. From all of them I like this one at most:
http://blogs.msdn.com/b/alexj/archive/2009/06/05/tip-23-how-to-fake-enums-in-ef-4.aspx?PageIndex=2#comments
This workaround allows you to use enums in your LINQ queries which is what i exactly need. However, I have a problem with this workaround. I get for every complex type I'm using a new partial autogenerated class.Therefore the code does not compile any more because I already have a wrapper class with this name in the same namespace which converts betwen the backed integer in the database and the enum in my POCO classes. If I make my wrapper a partial class, the code still does not compile as it now contains two properties with the same name "Value". The only possibility is to remove the Value property by hand everytime I generate the POCO classes because the DB model changed (which during the development phase happens very often).
Do you know how to prevent a partial class to be generated out of complex property everytime the EF model changes?
Can you recommend me some other workarounds supporting enumerations in LINQ queries?
That workaround is based on the fact that you are writing your POCO classes yourselves = no autogeneration. If you want to use it with autogeneration you must heavily modify T4 template itself.
Other workaround is wrapping enum conversion to custom extension methods.
public static IQueryable<MyEntity> FilterByMyEnum(this IQueryable<MyEntity> query, MyEnum enumValue)
{
int val = (int)enumValue;
return query.Where(e => e.MyEnumValue == val);
}
You will then call just:
var data = context.MyEntitites.FilterByMyEnum(MyEnum.SomeValue).ToList();
I am using an approach based on the one described in your link without any modifications of the T4 templates. The contents of my partial wrapper classes are as follows:
public partial class PriorityWrapper
{
public Priority EnumValue
{
get
{
return (Priority)Value;
}
set
{
Value = (int)value;
}
}
public static implicit operator PriorityWrapper(Priority value)
{
return new PriorityWrapper { EnumValue = value };
}
public static implicit operator Priority(PriorityWrapper value)
{
if (value == null)
return Priority.High;
else
return value.EnumValue;
}
}
I've only changed that instead of a back store variable with enum value I am using the autogenerated int typed Value property. Consequently Value can be an auto-implemented property and EnumValue property needs to do the conversion in getter and setter methods.

Resources