array <byte>^ in dictionary - c++-cli

I want to store an image data in an array byte into a dictionary.
int img_sz = img0->width * img0->height * img0->nChannels;
array <Byte>^ hh = gcnew array<Byte> (img_sz);
Marshal::Copy( (IntPtr)img->imageData, hh, 0, img_sz );
Dictionary<String^,array< Byte >^>^ myResult = gcnew Dictionary<String^,array< Byte >^>();
myResult->Add("OVERVIEW",hh);
Once it reaches the line myResult->Add("OVERVIEW",hh);
I am getting an :An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll

Check for duplicate keys. Dictionary::Add can't be used to replace existing data.
You can see the error explained in the documentation right here. It specifically says
ArgumentException An element with the same key already exists in the Dictionary.

Related

How do I convert array<unsigned char> to an unsigned char[]?

In a CLR project I have the output of AesManaged class as a 16 byte array
array<unsigned char>^ result = msEncrypt->ToArray();
However I need to convert this to an array of type unsigned char defined like this
unsigned char buff[16];
EDIT: I did try this but its giving error (no method signature with those parameters, although there is one)
System::Runtime::InteropServices::Marshal::Copy(result, 0, buff, 16);
And this one
buff = reinterpret_cast<unsigned char>(&result);
But the error is Expression must be a modifiable lvalue
According to this MSDN documentation I used this and it appears to work
pin_ptr<unsigned char>buff = &result[0];

List instead of array

I currently have a function with output myResult a dictionary of array of byte. I want to convert it into a dictionary of list of byte since for each entry I may store more than 1 array of byte. What is the format to replace the array with a list and how do I add each array to the list. The current format is the following:
int img_sz = img0->width * img0->height * img0->nChannels;
array <Byte>^ hh = gcnew array<Byte> (img_sz);
Marshal::Copy( (IntPtr)img->imageData, hh, 0, img_sz );
Dictionary<String^,array< Byte >^>^ myResult = gcnew Dictionary<String^,array< Byte >^>();
myResult["OVERVIEW"]=hh;
Any help is appreciated.
I'm not entirely sure which one of these you're going for, so I'll answer them both.
Dictionary<String^, List<Byte>^>^
If you want to end up with Dictionary<String^, List<Byte>^>^, just call the List<T> constructor that takes an IEnumerable<T>, and add it to the dictionary as you are now.
Dictionary<String^,List<Byte>^>^ myResult = gcnew Dictionary<String^,List<Byte>^>();
myResult["OVERVIEW"] = gcnew List<Byte>(hh);
Dictionary<String^, List<array<Byte>^>^>^
If you want to end up with Dictionary<String^, List<array<Byte>^>^>^, you'll need to check the dictionary to see if it as a list for that key yet, add the list if not, and then add the new array to the list. Call this method with the various arrays and name of the list you want to store each of them in.
void AddToResults(Dictionary<String^, List<array<Byte>^>^>^ myResult,
String^ key,
array<Byte>^ hh)
{
List<array<Byte>^>^ thisList;
if(!myResult->TryGetValue(key, thisList))
{
thisList = gcnew List<array<Byte>^>();
myResult->Add(key, thisList);
}
thisList->Add(hh);
}

c++/cli Dictionary within a function argument

I am getting familiar with c++/cli. I am writing a function called Locate with a class called Locator. The function that takes input a dictionary of strings.
Dictionary<String^, array< Byte >^>^ Locate(Dictionary<String^, String^>^ imgParms)
I am trying to call it in the main function by doing this:
Locator r;
Dictionary<String^,String^> myDictionary =
gcnew Dictionary<String^,String^>();
r.Locate(myDictionary);
but I am getting this error
error C3073: 'System::Collections::Generic::Dictionary<TKey,TValue>' : ref class does
not have a user-defined copy constructor with
[
TKey=System::String ^,
TValue=System::String ^
]
Any help would be appreciated.
Dictionary<String^,String^> myDictionary =
gcnew Dictionary<String^,String^>();
Should be
Dictionary<String^,String^>^ myDictionary =
gcnew Dictionary<String^,String^>();
the ^ symbol can be thought of as a type modifier like * do gcnew is returning you ax^ to type x

Accessing a SafeArray of Variants with JNI

I have a VB6 ActiveX DLL with functions that return a Variant. The Variant contains an array of node Variants, each of which contains a string Name and two data arrays (string and double). I am attempting to return this to a Java program as a jobject through JNI.
I can access the outer array of nodes by calling the appropriate VB function and storing the Variant result as a SAFEARRAY. It can access the dimension and get lower and upper bounds. However, I cannot access each node through SafeArrayGetElement() or SafeArrayAccessData(). I always get an Invalid Argument exception.
1) Can I pass or cast the SAFEARRAY (or VARIANT) directly to a jobject without iterating through the nodes in C++?
2) Am I using the wrong parameters to get the SAFEARRAY data? Does the size of the access pointer (var) need to be allocated beforehand?
SAFEARRAY* outarr = t->VBFunction(&bstrparam).GetVARIANT().parray;
//Returns correct dimension (1)
printf("JNI GetNodes_States: Got array, dimension %d\n", outarr->cDims);
//Returns correct bounds
LONG lBound, rBound;
SafeArrayGetLBound(outarr, 1, &lBound);
SafeArrayGetUBound(outarr, 1, &rBound);
printf("JNI GetNodes_States: Bounds [%d, %d]\n", lBound, rBound);
//Returns Invalid Argument error (hresult=0x80070057)
//Gets first element
LONG* indexArray = new LONG[outarr->cDims];
for(unsigned short i=0; i<outarr->cDims; ++i)
indexArray[i] = 0;
_variant_t var;
hresult = SafeArrayGetElement(outarr, indexArray, (void*)&var);
if (SUCCEEDED(hresult)){
printf( "JNI GetNodes_States: %s, %d\n", "", outarr->cDims);
}
else {
printf( "JNI GetNodes_States Access Error:%X\n", hresult);
outobj = NULL;
}
delete[] indexArray;
1) Can I pass or cast the SAFEARRAY (or VARIANT) directly to a jobject without iterating through the nodes in C++?
Absolutely not, I'm afraid. You're going to walk through the array, extract all the necessary values, and convert each of them to something that Java will understand.
2) Am I using the wrong parameters to get the SAFEARRAY data? Does the size of the access pointer (var) need to be allocated beforehand?
The most suspicious argument is indexArray, which you're setting to 0 for each dimension. However, if the array was created by Visual Basic it is quite possible that it is a 1-based array instead of a 0-based array, which would make an index of 0 illegal.
This is why your element-extraction code needs to pay attention to the results of SafeArrayGetLBound and SafeArrayGetUBound.

Copying a value in an array to a variable

I have an array of type int. It has one place and I want to copy that to a variable of type int.
Ex:
Random randomNum = new Random();
int myNumber = randomNum.Next(1,1000);
int[] puterNumber = new int[1];
puterNumber[ 1 ] = myNumber;
Later in my code..
int myPuterNumber;
myPuterNumber = puterNumber[ 1 ];
I get a message on mouseover saying 'Cannot resolve symbol 'puterNumber' '
Am I missing a step for copying the value of the array to an int variable?
This looks like a scope error, probably due to object structure if you are using Java. Honestly more code would help make it clear where exactly the problem was originating from.