How to find size of the 2D objectArray in JNI - android-ndk

I want to find the numbers of row and column in the 2D objectArray of JNI. how i can do? please anybody can help me for this problem.

If you have array of array, you have to go via array of objects.
1d arrays from java are 1d arrays of primitives in JNI
2d arrays are arrays of objects
So, for code like this:
public class PassArray {
public static native void passBooleanArray(boolean [][] array);
public static void main(String[] args) {
boolean [][] boolArray = { { true, true, true }, {false, false, false} };
passBooleanArray(boolArray);
}
}
you need something like this:
/* get size of the array */
jsize len = (*env)->GetArrayLength(env, array);
for(int i=0; i<len; i++) {
/* get the array at following indexes of array; it will be referecende by C pointer */
jbooleanArray body = (*env)->GetObjectArrayElement(env, array, i);
jsize innerLen = (*env)->GetArrayLength(env, body);
jboolean *booleanBody = (*env)->GetBooleanArrayElements(env, body, 0);
for(int j=0; j<innerLen; j++) {
/* do some stuff */
printf("Boolean value: %s\n", booleanBody[j] == JNI_TRUE ? "true" : "false");
}
/* release body when you decide it is no longer needed */
(*env)->ReleaseBooleanArrayElements(env, array, booleanBody, 0);
}
Update:
take a look here:
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo026
for a working sample code.

Related

Trying to replace delete pointer call with std::unique_ptr call

I am getting myself confused again with unique pointers and deletion.
I am trying to avoid the need for the delete pWidth line below:
void CCreateReportDlg::DeleteColumnWidthMap(CMapWordToPtr& rMapColumnWidth)
{
WORD wColumn{}, * pWidth = nullptr;
auto sPos = rMapColumnWidth.GetStartPosition();
while (sPos != nullptr)
{
rMapColumnWidth.GetNextAssoc(sPos, wColumn, reinterpret_cast<void*&>(pWidth));
if (pWidth != nullptr)
{
//delete pWidth;
std::unique_ptr<WORD*> cleanup(pWidth);
}
}
rMapColumnWidth.RemoveAll();
}
Why is it saying this?
Ah, I think I now see that the unique_ptr is supposed to be an array of WORD pointers. But I only have just the one value.
Update
Example of how I populate the map (parameter to function):
void CCreateReportDlg::HideColumns(CGridCtrl* pGrid, const CDWordArray* pAryDWColumns, CMapWordToPtr& rMapColumnWidth)
{
ASSERT(pGrid != nullptr);
ASSERT(pAryDWColumns != nullptr);
if (pGrid == nullptr || pAryDWColumns == nullptr)
return;
DeleteColumnWidthMap(rMapColumnWidth);
const auto iSize = pAryDWColumns->GetSize();
for (INT_PTR i = 0; i < iSize; i++)
{
const auto dwColumnData = pAryDWColumns->GetAt(i);
const auto iCol = LOWORD(dwColumnData);
const auto eImage = static_cast<CheckImageIndex>(HIWORD(dwColumnData));
if (eImage == CheckImageIndex::Unchecked)
{
auto pWidth = std::make_unique<WORD>().release();
ASSERT(pWidth != nullptr);
if (pWidth != nullptr)
{
*pWidth = pGrid->GetColumnWidth(iCol);
rMapColumnWidth.SetAt(iCol, pWidth);
}
pGrid->SetColumnWidth(iCol, 0);
}
}
}
Use {std::unique_ptr<WORD> cleanup(pWidth);} for deleting pWidth = std::make_unique<WORD>().release();
But std::map<int,int> (or unordered_map) is a much better than CMapWordToPtr, you don't need to store a pointer here.
You should be able to simplify your function like this:
void HideColumns(CGridCtrl* pGrid,
std::vector<DWORD> &pAryDWColumns, std::map<int,int> &rMapColumnWidth)
{
//clear the map, it doesn't need separate function
rMapColumnWidth.clear();
for (auto dword : pAryDWColumns)
{
const auto iCol = LOWORD(dword);
const auto eImage = static_cast<CheckImageIndex>(HIWORD(dword));
if (eImage == CheckImageIndex::Unchecked)
{
rMapColumnWidth[iCol] = pGrid->GetColumnWidth(iCol);
pGrid->SetColumnWidth(iCol, 0);
}
pGrid->SetColumnWidth(iCol, 0);
}
}
...
for (auto e : map)
TRACE("%d\n", e);
By the way, in another question I think I recommended using std::unique_ptr to turn off some Code Analysis messages. You should ignore that advice. Either stick with new/delete or use STL classes which have automatic memory management.
You can still use std::unique_ptr in some special cases, for example when passing data to APIs or some MFC functions.

Is there appropiate way that each object is generated with a new name

using System;
namespace rummykhan
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Test t1 = new Test();
}
}
}
class Test
{
public int first;
public int second;
}
}
im trying to make 100 objects but i wish these objects are named automatically using some random string. im unable to figure out.. thanx for help in advance..
EDIT
Looking at my own question after a year, actually i was looking for a way by which i was able to create object by my own chosen name. e.g.
string tmp = "obj1";
var tmp = new Foo();
i was thinking that someway obj1 value may kick in and i could call my variable using obj1, which is totally moronic.
Just store the objects in a List.
example:
List<Test> tests = new List<Test>();
for (int i = 0; i < 100; i++)
{
tests.Add(new Test());
}
Currently your code will destroy t1 after each iteration of the loop. you could do something like this to preserve 100 coppies of test in memory
using System;
namespace rummykhan
{
class Program
{
static void Main(string[] args)
{
List<Test> lstClasses = new List<Test>();
for (int i = 0; i < 100; i++)
{
lstClasses.Add(new Test());
}
}
}
class Test
{
public int first;
public int second;
}
}
write like this.
Test[] dynamic = new Test[100];
for (int i=0; i< 100; i++)
{
dynamic[i] = new Test();
}

concatenating existing strings within an array into new strings of a new array

I'm trying to get this program's groupPairs function to take the six Strings in an initial String array [One,Two,Three,Four,Five,Six] and create a new String array of half the size (3) with the original six Strings grouped sequentially in pairs [OneTwo,ThreeFour,FiveSix], and then return that resulting new String[] to the main method.
import java.util.*;
public class Application
{
static String[] groupPairs(String[] array)
{
String[] newArray = new String[(array.length)/2];
int count=0;
for(String string:newArray)
{
newArray[count]=array[count].append(array[count+1]);
count=count+2;
}
return newArray;
}
public static void main(String args[]) //main method, don't worry about this
{
String[] list = new String[5];
list[0]="One";
list[1]="Two";
list[2]="Three";
list[3]="Four";
list[4]="Five";
list[5]="Six";
String[] list2 = groupPairs(list);
}
}
When trying to compile the program, I get this error:
Application.java:11: cannot find symbol
symbol : method append(java.lang.String)
location: class java.lang.String
newArray[count]=array[count].append(array[count+1]);
^
Any ideas on how to fix this line so that my new array will have concatenated pairs of the original String[] values would be greatly appreciated!
You cannot perform append operation on array. Try the following.
String[] list = new String[6];
list[0] = "One";
list[1] = "Two";
list[2] = "Three";
list[3] = "Four";
list[4] = "Five";
list[5] = "Six";
String[] list2 = new String[list.length / 2];
for (int i = 0, j = 0; i < list.length; i++, j++)
{
list2[j] = list[i] + list[++i];
}

Java ME Utility Functions

JavaME is quite sparse on features. Please list your favourite utility functions for making using it more like using proper Java, one per answer. Try to make your answers specific to Java ME.
Small Logging Framework
MicroLog
http://microlog.sourceforge.net/site/
Splitting a string
static public String[] split(String str, char c)
{
int l=str.length();
int count = 0;
for(int i = 0;i < l;i++)
{
if (str.charAt(i) == c)
{
count ++;
}
}
int first = 0;
int last = 0;
int segment=0;
String[] array = new String[count + 1];
for(int i=0;i<l;i++)
{
if (str.charAt(i) == c)
{
last = i;
array[segment++] = str.substring(first,last);
first = last;
}
if(i==l-1){
array[segment++] = str.substring(first,l);
}
}
return array;
}
Read a line from a reader. See also this question.
public class LineReader{
private Reader in;
private int bucket=-1;
public LineReader(Reader in){
this.in=in;
}
public boolean hasLine() throws IOException{
if(bucket!=-1)return true;
bucket=in.read();
return bucket!=-1;
}
//Read a line, removing any /r and /n. Buffers the string
public String readLine() throws IOException{
int tmp;
StringBuffer out=new StringBuffer();
//Read in data
while(true){
//Check the bucket first. If empty read from the input stream
if(bucket!=-1){
tmp=bucket;
bucket=-1;
}else{
tmp=in.read();
if(tmp==-1)break;
}
//If new line, then discard it. If we get a \r, we need to look ahead so can use bucket
if(tmp=='\r'){
int nextChar=in.read();
if(tmp!='\n')bucket=nextChar;//Ignores \r\n, but not \r\r
break;
}else if(tmp=='\n'){
break;
}else{
//Otherwise just append the character
out.append((char) tmp);
}
}
return out.toString();
}
}

Continuously add digits to a string

Just a quick one, I want to continuously add digits to a string. The first thing I did is to remove the last character of the string, now digits starting from 1 should be continuously added to it. The snippet is below:
using System;
using System.Collections.Generic;
namespace ConsoleApplication3
{
class Class1
{
public static String source = "#box1";
static string dest;
public static void Main(String[] args)
{
try
{
if (source.Length > 0)
{
dest = source.Substring(0, source.Trim().Length - 1);
}
Console.WriteLine(dest);
Console.ReadLine();
}
catch(Exception e){ e.ToString(); }
}
}
}
The output should look like this:
#box1
#box2
#box3
#box4
#box5
and so on.....
If you have a max :
for (int i = 1; i <= max; i++)
{
Console.WriteLine("#Box" + i);
}
With no maximum, but that is not a good idea:
count = 1
while (1 > 0)
{
Console.WriteLine("#Box" + count);
count++;
}
You can also do no max with the for loop, but I just wanted to give you more options in loops.
Information on loops http://csharp.net-tutorials.com/basics/loops/
Thanks, guys,
I got it solved this way. Sorry that I have to post the real code I'm using it for. I'm much occupied than to edit the pseudo code again.
public static String RegistrationFailedPanels = UserValidations.RegistrationFailedPanels;
public static String CloseFailedPanel = UserValidations.CloseFailedPanel;
static int count = 0;
public void LoginFailed(String InputConstant, String FailedLogin)
{
++count;
InputConstant = RegistrationFailedPanels.Substring(0, RegistrationFailedPanels.Trim().Length-1);
FailedLogin = CloseFailedPanel.Substring(0, CloseFailedPanel.Trim().Length-1);
new LoginValidations(driver).WaitForATime(InputConstant +count);
driver.FindElement(By.CssSelector(FailedLogin +count)).Click();
}

Resources