C++ Make Your Own Class asValue for dictionary - c++-cli

I am using VS2010, c++ windows forms application.
Here is my class
#pragma once
public ref class FrameMatrix
{
public:
FrameMatrix(void);
FrameMatrix(int IdNm, int ClmnAmnt, int RwsAmnt);
String^ FMName;
int FMIdentificationNumber;
array<array<double>^>^ FMArray;
};
Now I try to put it into Dictionary as value.
And I get unresolved tokens.
#pragma once
#include "FrameMatrix.h"
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Dictionary<int, FrameMatrix^>^ ImportedData;
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
ImportedData = gcnew Dictionary<int, FrameMatrix^>;
}

You forgot the parentheses:
ImportedData = gcnew Dictionary<int, FrameMatrix^>();
^^
If that doesn't fix the error, please post the exact error message you're getting.

Related

__property to property

I am converting a project from /oldsyntax to /clr and have problems to convert my properties in the public __gc class Reader which has now become public ref class Reader
I have these properties (amongst others) in the .h file
__property void set_Xml(System::String *value);
__property System::String *get_Xml();
and then in the .cpp file I have
void Reader::set_Xml(System::String *value)
{
if(value->Chars[0] == '<'){
reader->put_xml(stlString(value).c_str());
}
else {
reader->put_xml_file(stlString(value).c_str());
}
}
System::String *Reader::get_Xml()
{
return gcString(reader->get_xml(), reader->state.is_utf8);
}
How do I rewrite this so that it can compile with /clr. I am using Visual Studio 2010 ?
The link posted in the comments has all the information on the new syntax for properties.
Old: Declare methods with a specific naming convention, decorate them with __property.
New: Declare a property block within your class, and have methods with an additional level of scope. (Note: I'm not sure if "additional level of scope" is the proper way to describe it, see below.)
For a property named Xml of type String, the syntax would be:
In the header file:
public ref class Reader
{
public:
property String^ Xml
{
String^ get();
void set(String^ value);
}
}
In the .cpp file:
String^ Reader::Xml::get()
{
return whatever;
}
void Reader::Xml::set(String^ value)
{
whatever = value;
}

Can't reference C++/cx class from xaml? (UWP)

I have a C++ class in my application testclient:
namespace testclient{
namespace models{
ref class myclass sealed{
public:
myclass();
property String^ getstring
{
String^ get()
{
return string;
}
}
private:
String^ string = "test";
}}}
I want to bind a control to the property getstring, and from what little I understand of UWP XAML data binding, I have to include this in the top of the MainPage.xaml: xmlns:data="using:testclient.models Problem is, intellisense is telling me "Undefined namespace. The 'using' URI refers to a namespace called testclient.models that could not be found." What am I doing wrong?
EDIT: I've found the problem goes away when I put the class in Mainpage.Xaml.h, but I'd rather not do this...
Every binding consists of a binding target and a binding source. Typically, the target is a property of a control or other UI element, and the source is a property of a class instance.
If you want to use myclass as datasource to MainPage's UI elements, you need to make sure the instance of the myclass is accessible to MainPage. That's why your first version resulted in error. In order to modify mainPage.Xaml.h as little as possible, you could follow steps below by creating a separate file(I simplified the member of myclass for easy debugging):
1) Create myclass.h:
namespace TestClient{
namespace models{
public ref class myclass sealed
{
private:
int test = 1;
public:
myclass()
{
}
property int gettest
{
int get() { return test; };
}
};
}
}
2) in MainPage.h, add following:
#include "myclass.h"
namespace TestClient
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public ref class MainPage sealed
{
private:
TestClient::models::myclass myTest;
.......
}
.........
}
3) Then you can manipulate myclass data in mainPage.cpp as you want. Codes may be like below:
MainPage::MainPage()
{
InitializeComponent();
int i = this->myTest.gettest;
...........
}
Still I have a question: while so many namespace nested? Also you can find a sample about data binding here just for your reference.

What is the syntax to declare a C++/CX WinRT property with implementation in the .cpp file?

I have a class like this:
public ref class Test
{
public:
property int MyProperty;
};
This works. Now I want to move the implementation of MyProperty to the CPP file. I get compiler errors that the property is already defined when I do this:
int Test::MyProperty::get() { return 0; }
What is the proper syntax for this?
In the header change the declaration to:
public ref class Test
{
public:
property int MyProperty
{
int get();
void set( int );
}
private:
int m_myProperty;
};
Then, in the cpp code file write your definitions like this:
int Test::MyProperty::get()
{
return m_myProperty;
}
void Test::MyProperty::set( int i )
{
m_myProperty = i;
}
The reason you are seeing errors is that you have declared a trivial property where the compiler generates an implementation for you. But, then you tried to provide an implementation explicitly as well. See: http://msdn.microsoft.com/en-us/library/windows/apps/hh755807(v=vs.110).aspx
Most of the examples online only show implementations directly in the class definition.
In the class definition, you need to declare the property as a property with user-declared get and set methods; it cannot be a shorthand property:
public ref class Test
{
public:
property int MyProperty { int get(); void set(int); }
};
Then in the cpp file you may define the get() and set() methods:
int Test::MyProperty::get()
{
return 42;
}
void Test::MyProperty::set(int)
{
// set the value
}

Passing an array of interfaces from C# to C++/CLI

I am trying to pass an array of interfaces from C# to C++/CLI. Here is the code:
// *** SafeArrayTesting_PlusPlus.cpp ***
#include "stdafx.h"
#include <comdef.h>
using namespace System;
using namespace System::Runtime::InteropServices;
namespace SafeArrayTesting_PlusPlus {
public ref class MyCppClass
{
public:
MyCppClass();
~MyCppClass();
void SetMyInterfaces(
array<SafeArrayTesting_Sharp::MyInterface^>^ myInterfaces);
};
MyCppClass::MyCppClass(){}
MyCppClass::~MyCppClass(){}
void MyCppClass::SetMyInterfaces(array<SafeArrayTesting_Sharp::MyInterface^>^
myInterfaces)
{
// Create safearray
SAFEARRAY *safeArrayPointer;
SAFEARRAYBOUND arrayDim[1]; // one dimensional array
arrayDim[0].lLbound= 0;
arrayDim[0].cElements= myInterfaces->Length;
safeArrayPointer = SafeArrayCreate(VT_UNKNOWN,1,arrayDim);
// copy ints to safearray
for (long lo= 0;lo<myInterfaces->Length;lo++)
{
IntPtr myIntPtr = Marshal::GetIUnknkownForObject(myInterfaces[lo]);
SafeArrayPutElement(
safeArrayPointer,
&lo,
static_cast<void*>(myIntPtr)
);
}
// do something with the safearray here - area XX
}}
// *** SafeArrayTesting_Main.cs ***
using SafeArrayTesting_PlusPlus;
using SafeArrayTesting_Sharp;
namespace SafeArrayTesting_Main
{
class SafeArrayTesting_Main
{
static void Main()
{
var myCppClass = new MyCppClass();
MyInterface myInterface = new MyClass();
myCppClass.SetMyInterfaces(new[]{ myInterface });
}
}}
// *** SafeArrayTesting_Sharp.cs ***
using System;
using System.Runtime.InteropServices;
namespace SafeArrayTesting_Sharp
{
[ComVisible(true)]
public interface MyInterface
{
int MyInt { get; set; }
string MyString { get; set; }
DateTime MyDateTime { get; set; }
}
[ComVisible(true)]
public class MyClass : MyInterface
{
public int MyInt{get;set;}
public string MyString{get;set;}
public DateTime MyDateTime{get; set;}
}
// Just to please the compiler; bear with me.
class DummyClass { static void Main() { } }
}
As written here, the code runs and compiles cleanly. However, when running the "area XX" part, I get a System.Runtime.InteropServices.SEHException.
The XX code is just a single line which calls an auto-generated method accepting a SAFEARRAY pointer. Here is the declaration of this method (from a .tlh file):
virtual HRESULT __stdcall put_SafeArray (
/*[in]*/ SAFEARRAY * pRetVal ) = 0;
I actually think this method converts the SAFEARRAY back to a .NET array - it's all part of a conversion project my company is running at the time. So there is no alternative to using a SAFEARRAY.
Anyway, it would really surprise me if the code without the XX part is bug-free; I'm quite a novice when it comes to C++. Can you help me spot some of the problems? If anyone can suggest a better way of testing the validity of the SAFEARRAY that would also be a help.
(By the way, this is a more complex variation of the question SafeArrayPutElement method throws System.AccessViolationException , in which I was just passing an array of ints from C# to C++/CLI.)
Several problems. For one, you don't actually store a VARIANT in the array. This is ultimately not going anywhere, a SafeArray cannot store references to managed objects. The garbage collector moves objects around, it cannot see references held by unmanaged code so it cannot update the reference.
At best, you could create an array of VT_UNKNOWN or VT_DISPATCH. But you can't get the COM interface pointer for these managed objects, they are not [ComVisible]. When you fix that, you'd use Marshal.GetIDispatchForObject() or Marshal.GetIUnknownForObject() to get the interface pointer to store in the array.

Implementing an interface declared in C# from C++/CLI

Say I have a C# interface called IMyInterface defined as follows:
// C# code
public interface IMyInterface
{
void Foo(string value);
string MyProperty { get; }
}
Assume I also have a C++/CLI class, MyConcreteClass, that implements this interface and whose header is declared as follows:
// C++/CLI header file
ref class MyConcreteClass : IMyInterface
{
public:
};
How does one implement the method Foo and the property MyProperty in the C++/CLI header?
My attempt results in the following compile error:
error C3766: 'MyConcreteClass' must
provide an implementation for the
interface method 'void
IMyInterface::Foo(System::String^
value)'
public ref class MyConcreteClass : public IMyInterface
{
public:
virtual void __clrcall Foo(String^ value) sealed;
virtual property String^ __clrcall MyProperty
{ String^ get() sealed { String::Empty; } }
};
Interfaces need to be defined as virtual. Also note the "public IMy.." after the class decleration, it's a slighly different syntax than C#.
If you can, seal the interface members to improve performance, the compiler will be able to bind these methods more tightly than a typical virtual members.
Hope that helps ;)
I did not compile it but looks good to me... Oh and also, defining your methods as __clrcall eliminates dangers of double thunk performance penalties.
edit
the correct syntax for a property is:
public ref class MyConcreteClass : public IMyInterface
{
public:
virtual property String^ MyProperty
{
String^ get() sealed { return String::Empty; };
void set( String^ s ) sealed { };
}
};
or, when putting the definition in the source file:
public ref class MyConcreteClass : public IMyInterface
{
public:
virtual property String^ MyProperty
{
String^ get() sealed;
void set( String^ s ) sealed;
}
};
String^ MyConcreteClass::MyProperty::get()
{
return String::Empty;
}
void MyConcreteClass::MyProperty::set( String^ )
{
//...
}