Dictionary with byte array argument - c++-cli

I have a dictionary myResult:
Dictionary<String^,array< Byte >^>^ myResult = gcnew Dictionary<String^,array< Byte >^>();
I am declaring
array <Byte^>^ a;
and then I am adding a to a key of the dictionary
myResult->Add("OVERVIEW",a);
I am getting an error
error C2664: 'System::Collections::Generic::Dictionary<TKey,TValue>::Add' :
cannot convert parameter 2 from 'cli::array<Type> ^' to 'cli::array<Type> ^'
1> with
1> [
1> TKey=System::String ^,
1> TValue=cli::array<unsigned char> ^
1> ]
1> and
1> [
1> Type=System::Byte ^
1> ]
1> and
1> [
1> Type=unsigned char
1> ]
Any help is appreciated since I am still not very familiar with c++/cli;

Dictionary<String^,array< Byte >^>^
^ Uppercase B
array <byte^>^ a;
^ Lowercase B
Byte^ and byte^ name different types (actually, I am somewhat surprised that the latter compiles, though I am not a C++/CLI expert). The former is a tracking handle to a System::Byte. The latter is an unsigned char (apparently the compiler is dropping the hat, I presume it does so because it is not a CLI type, making it ineligible to wear hats).

Related

How do I create a std::filesystem::exists() compatible path from Windows::Storage::StorageFile? [duplicate]

I'm trying to open a file using a string parameter, however I'm getting the following error:
error C2664: 'void std::basic_ifstream<_Elem,_Traits>::open(const wchar_t *,std::ios_base::openmode,int)' : cannot convert parameter 1 from 'System::String ^' to 'const wchar_t *'
How do you convert System::String ^ to const wchar_t *?
As Hans points out, simple conversion is necessary. It would look similar to the following:
System::String ^str = L"Blah Blah";
pin_ptr<const wchar_t> convertedValue = PtrToStringChars(str); // <-- #include <vcclr.h>
const wchar_t *constValue = convertedValue; // <-- Unnecessary, but to be completely verbose
void std::basic_ifstream<_Elem, _Traits>::open(constValue, mode, i);

Jasmin array of Strings declaration/initialization error

I'm writing a compiler that generates Jasmin code and want to create an array declaration as follows:
string[] name = { "asd", "asd" };
This currently generates the following code:
ldc 2 ; array size
newarray char ; create new array of chars
astore 8 ; store array at loc 8
ldc "asd" ; push value 1 onto stack
ldc 0 ; push index onto stack
aload 8 ; push array reference onto stack
aastore ; store value in array at index
ldc "asd" ; push value 2 onto stack
ldc 1 ; push index onto stack
aload 8 ; push array reference onto stack
aastore ; store value in array at index
I thought this was the correct way, but I'm getting the following error:
java.lang.VerifyError: (class: helloworld, method: main signature: ([Ljava/lang/String;)V) Expecting to find array of objects or arrays on stack
Am I pushing things onto the stack in the wrong order? Or should I use a different type than char at the newarray line. If so, What's the correct type to use for Strings?
Never mind, I solved it already.
Should have used the following line to create an array of objects of type String:
anewarray Ljava/lang/String;

Copy two dimensional arrays using pointers

I want to copy two dimensional arrays and I made this function but it caused a compilation error
void Cpy_2d_arr(unsigned char *from,unsigned char *to)
{
unsigned char col,row;
for (row=0;row<4;row++)
{
for(col=0;col<4;col++)
{
(*(*(to+row)+col)) = (*(*(from+row)+col));
}
}
}
The two dimensional arrays are
unsigned char arr[4][4] = {'7','8','9','-','4','5','6','*','1','2','3','-','c','0','=','+'};
the target is an array inside a struct with the same size
the errors are :
1- Error 8 expected 'unsigned char ' but argument is of type 'unsigned char ()[4]
2- Error 11 subscripted value is neither array nor pointer
3- Error 11 invalid type argument of unary '*' (have 'int')
char arr[4][4] = {'7','8','9','-','4','5','6','*','1','2','3','-','c','0','=','+'};
is an array of pointers
void Cpy_2d_arr(unsigned char *from,unsigned char *to)
receives an single pointer( e.g. to an array of chars).
the types of your parameters are not compatible, change it to
void Cpy_2d_arr(unsigned char from[4][4],unsigned char to[4][4])
it should work just fine

Defining custom input types for the new yaml-cpp API

I am trying to define some custom input types using the new-style YamlCpp API. I have two questions. Let me first say that we are currently using the 0.3 style-api and everything works great. The code-appearance of the new API is about 10x better though so we wanted to move to it.
Why does my current approach bork the compiler?
Is yaml-cpp smart enough to handle nested templates. For example, if my parser knows how to enc/dec std::vectors, and then I define a custom handler for MyAwesomeType separately -- can I ask it to enc/dec a std::vector<MyAwesomeType> and it will figure it out?
My code began by copying and pasting the example on the website (here) and then modifying that. My current implementation attempts to handle conversion of std::vector<std::pair<qint16,qint16>> -- this does not compile. (fyi - qint16 is simply a cross-platform typedef for __int16)
#include "yaml-cpp\yaml.h"
#include <vector>
#include "qglobal.h"
namespace YAML {
// a std::pair of qint16's
template<>
struct convert<std::pair<qint16,qint16>> {
static Node encode( std::pair<qint16,qint16> const& rhs) {
Node node;
std::vector<qint16> newVec;
newVec.push_back(rhs.first);
newVec.push_back(rhs.second);
node = newVec;
return node;
}
static bool decode(Node const& node, std::pair<qint16,qint16> & rhs) {
if(!node.IsSequence() || node.size() != 2) {
return false;
}
rhs.first = node[0].as<qint16>();
rhs.second = node[1].as<qint16>();
return true;
}
};
// a vector of std::pair of qint16's
template<>
struct convert<std::vector<std::pair<qint16,qint16>>> {
static Node encode( std::vector<std::pair<qint16,qint16>> const& rhs) {
Node node;
for(auto pairIt=rhs.begin();pairIt!=rhs.end();++pairIt)
{
node.push_back( *pairIt );
}
return node;
}
static bool decode(Node const& node, std::vector<std::pair<qint16,qint16>> & rhs) {
if( !node.IsSequence() ) {
return false;
}
for(int k=0;k<node.size();++k)
{
rhs.push_back( node[k].as<std::pair<qint16,qint16>>() );
}
return true;
}
};
}
Finally, I would like to then use this to call
std::map<std::string, std::vector<std::pair<qint16, qint16>>> m_vectorOfPairs;
if( doc["myPairs"] )
{
// key exists!
for( YAML::const_iterator it=doc["myPairs"].begin();it!=doc["myPairs"].end();++it)
{
m_vectorOfPairs[it->first.as<std::string>()] = it->second.as<std::vector<std::pair<qint16,qint16>>>();
}
}
...based on input yaml which looks like this...
myPairs:
pairOne: [[4, 25], [48, 336]]
pairTwo: [[4, 25], [57, 336]]
pairThree: [[4, 25], [48, 336]]
The compiler error output from this is about 300 lines, so I will not post that here.
Platform: Visual Studio 2010 SP1 x64
Thanks for your help.
EDIT:
Here is the first of many errors I get, namely that it doesn't even seem happy parsing a Node key with the new style... I'm adding this because what is causing this may be related to the other errors.
Code
YAML::Node doc = YAML::LoadFile(buildFilenamePath(m_spectCameraShortName, relativePath).toStdString());
if( doc["numPixels"] )
//...
Causes
1>ANONPATH\thirdparty\yaml-cpp\include\yaml-cpp/node/detail/impl.h(146): error C2734: 'lhs' : const object must be initialized if not extern
1> ANONPATH\thirdparty\yaml-cpp\include\yaml-cpp/node/detail/impl.h(96) : see reference to function template instantiation 'bool YAML::detail::node_data::equals<const char[10]>(YAML::detail::node &,T (&),YAML::detail::shared_memory_holder)' being compiled
1> with
1> [
1> T=const char [10]
1> ]
1> ANONPATH\thirdparty\yaml-cpp\include\yaml-cpp/node/detail/node_ref.h(52) : see reference to function template instantiation 'YAML::detail::node &YAML::detail::node_data::get<const char[10]>(Key (&),YAML::detail::shared_memory_holder)' being compiled
1> with
1> [
1> Key=const char [10]
1> ]
1> ANONPATH\thirdparty\yaml-cpp\include\yaml-cpp/node/detail/node.h(103) : see reference to function template instantiation 'YAML::detail::node &YAML::detail::node_ref::get<const char[10]>(Key (&),YAML::detail::shared_memory_holder)' being compiled
1> with
1> [
1> Key=const char [10]
1> ]
1> ANONPATH\thirdparty\yaml-cpp\include\yaml-cpp/node/impl.h(333) : see reference to function template instantiation 'YAML::detail::node &YAML::detail::node::get<const char[10]>(Key (&),YAML::detail::shared_memory_holder)' being compiled
1> with
1> [
1> Key=const char [10]
1> ]
1> MYCODEFILE.cpp(75) : see reference to function template instantiation 'YAML::Node YAML::Node::operator []<const char[10]>(Key (&))' being compiled
1> with
1> [
1> Key=const char [10]
1> ]
Note that the Line 75 mentioned in the error above is the
if( doc["numPixels"] )
line
I've recompiled from source latest using Rev 573 of default branch and all these examples are from that code.
Yes, yaml-cpp should be able to handle nested templates (and so you shouldn't need to define a conversion for std::vector<std::pair<qint16, qint16>> - and, this suggests that yaml-cpp should define a conversion for std::pair<T, U> in general (http://code.google.com/p/yaml-cpp/issues/detail?id=188)).
And I'm not sure why the compiler doesn't accept your code (it looks correct, and compiles fine on Linux for me).
Do the tests compile at all? Apparently, 0.5.0 doesn't work out of the box on Visual Studio (see http://code.google.com/p/yaml-cpp/issues/detail?id=182), and I haven't had a chance to test or merge the fix yet.

...array<Object^>^ args

I'm reading C++/CLI. I see this stuff:
Object^ CreateInstanceFromTypename(String^ type, ...array<Object^>^ args)
{
if (!type)
throw gcnew ArgumentNullException("type");
Type^ t = Type::GetType(type);
if (!t)
throw gcnew ArgumentException("Invalid type name");
Object^ obj = Activator::CreateInstance(t, args);
return obj;
}
When calling it:
Object^ o = CreateInstanceFromTypename(
"System.Uri, System, Version=2.0.0.0, "
"Culture=neutral, PublicKeyToken=b77a5c561934e089",
"http://www.heege.net"
);
What is ...array^ args? If I remove ... ,there's a complied-error:
error C2665: 'CreateInstanceFromTypeName' : none of the 2 overloads could convert all the argument types
1> .\myFourthCPlus.cpp(12): could be 'System::Object ^CreateInstanceFromTypeName(System::String ^,cli::array<Type> ^)'
1> with
1> [
1> Type=System::Object ^
1> ]
1> while trying to match the argument list '(const char [86], const char [21])'
Like C++, C++/CLI has a mechanism for a variable amount of arguments. That is what the ... in front of the ...array<Object^>^ parameter means.
For type safety the C++/CLI designers added managed syntax to declare the type of the variable array.
Since it's just passing that parameter to the Activator::CreateInstance() function, I would look at what variable parameters the Activator function is looking for.