jsm11482
asked on
Copying jobjectarray to CString[] with JNI
Please see original question here: https://www.experts-exchange.com/questions/21816693/Copying-jobjectarray-to-CString-with-JNI.html#16475666
Thank you,
Josh
Thank you,
Josh
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
<This _should_ really be continued in only 1 thread; jsm11482, which thread do you wish to continue this in? C++ or Java?>
>>>> For the first one, i do not want to add each char to the jobjectArray,
//CString array to jobjectArray
jobjectArray JNIUtil::CopyArray(JNIEnv* env, CString in[], int siz)
{
jobjectArray out = env->NewObjectArray(siz, env->FindClass("java/lang/ String"), NULL);
for (int i = 0; i < siz; i++)
env->SetObjectArrayElement (out, i, env->NewStringUTF(in[i]));
return out;
}
'CString in[]' is equivalent to CString* but you easier can see that it is an array of CStrings. The size of the array can't be detected from the argument as it turned to a pointer (size is always 4) when passed as an argument. So, you would need an additional argument as it would be with any C array. As an alternative you might use std::vector<CString> or CStringArray that were container classes with a size() or GetSize() function.
jobjectArray JNIUtil::CopyArray(JNIEnv* env, CStringArray in)
{
jobjectArray out = env->NewObjectArray(in->Ge tSize(), env->FindClass("java/lang/ String"), NULL);
for (int i = 0; i < in.GetSize(); i++)
env->SetObjectArrayElement (out, i, env->NewStringUTF(in[i]));
return out;
}
Regards, Alex
>>>> This _should_ really be continued in only 1 thread
As it is C++ code that is required I would suggest to let the solution here in C++ TA.
The Java thread may be closed as well as the maximum points for one question is not exceeded.
//CString array to jobjectArray
jobjectArray JNIUtil::CopyArray(JNIEnv*
{
jobjectArray out = env->NewObjectArray(siz, env->FindClass("java/lang/
for (int i = 0; i < siz; i++)
env->SetObjectArrayElement
return out;
}
'CString in[]' is equivalent to CString* but you easier can see that it is an array of CStrings. The size of the array can't be detected from the argument as it turned to a pointer (size is always 4) when passed as an argument. So, you would need an additional argument as it would be with any C array. As an alternative you might use std::vector<CString> or CStringArray that were container classes with a size() or GetSize() function.
jobjectArray JNIUtil::CopyArray(JNIEnv*
{
jobjectArray out = env->NewObjectArray(in->Ge
for (int i = 0; i < in.GetSize(); i++)
env->SetObjectArrayElement
return out;
}
Regards, Alex
>>>> This _should_ really be continued in only 1 thread
As it is C++ code that is required I would suggest to let the solution here in C++ TA.
The Java thread may be closed as well as the maximum points for one question is not exceeded.
correction:
jobjectArray JNIUtil::CopyArray(JNIEnv* env, const CStringArray& in)
{
jobjectArray out = env->NewObjectArray(in.Get Size(), env->FindClass("java/lang/ String"), NULL);
for (int i = 0; i < in.GetSize(); i++)
env->SetObjectArrayElement (out, i, env->NewStringUTF(in[i]));
return out;
}
jobjectArray JNIUtil::CopyArray(JNIEnv*
{
jobjectArray out = env->NewObjectArray(in.Get
for (int i = 0; i < in.GetSize(); i++)
env->SetObjectArrayElement
return out;
}
ASKER
please continue this thread in the C++ area
ASKER
ok so if i send a double array of {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} i am getting back an array of (| delimited):
0.0|0.0|0.0|0.0|0.0|0.0|0. 0|0.0|0.0| 0.0|0.0|0. 0|0.0|0.0| 0.0|0.0|0. 0|0.0|0.0| 0.0|0.0|0. 0|0.0|0.0| 0.0|0.0|0. 0|0.0|0.0| 0.0|0.0|0. 0|0.0|4.9E -324|-999. 0|-999.0|- 999.0|-999 .0|-999.0| -999.0|0.0 |0.05|1.0| 0.0|1.0|0. 0|0.0|0.0| 0.0|1.0162 08805E-315 |0.045|0.0 |0.0|1.496 7570022479 021E-249|2 .758594528 8E-313|0.0 |0.0|1.478 4031306360 101E-249|1 .060997895 73E-313|1. 2288611814 499066E-24 9|1.919967 8765E-313| 4.4E-323|0 .0|0.0|0.0 |0.0|0.0|0 .0|0.0|0.0 |0.0|0.0|0 .0|0.0|0.0 |0.0|0.0|0 .0|0.0|2.0 |1.0162088 05E-315|0. 03|0.04|0. 0|1.537211 390420101E -249|2.223 731269E-31 4|1.537207 1280969523 E-249|2.12 1995796E-3 14
trace:
calc.setPctSharesVestArray (new double[] {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
-> to C++ DLL convert jobjectArray to double array
calc.setPctSharesVestArray ()
-> to C++ DLL convert double array to jobjectArray
returns the long array above (after making the suggested code changes)
0.0|0.0|0.0|0.0|0.0|0.0|0.
trace:
calc.setPctSharesVestArray
-> to C++ DLL convert jobjectArray to double array
calc.setPctSharesVestArray
-> to C++ DLL convert double array to jobjectArray
returns the long array above (after making the suggested code changes)
>>>> calc.setPctSharesVestArray (new double[] {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
The code above isn't valid C++ code.
Please, post the original call that failed (plus array creation) and the code of the function that does the conversion( should be JNIUtil::CopyArray).
Regards, Alex
The code above isn't valid C++ code.
Please, post the original call that failed (plus array creation) and the code of the function that does the conversion( should be JNIUtil::CopyArray).
Regards, Alex
ASKER
The line: calc.setPctSharesVestArray (new double[] {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
is run in java via JNI, the array is passed to the following C++ function:
JNIEXPORT void JNICALL Java_com_towers_ltip_LTIPC alc_setPct SharesVest Array (JNIEnv *env, jobject obj, jint ptr, jdoubleArray value)
{
CLTIPCalc* calc = (CLTIPCalc*)ptr;
JNIUtil* util = new JNIUtil();
util->CopyArray(env, value, calc->m_adPctSharesVest);
}
i just want to copy the passed-in jdoubleArray to the member variable m_adPctSharesVest.
Sorry for the confusion.
is run in java via JNI, the array is passed to the following C++ function:
JNIEXPORT void JNICALL Java_com_towers_ltip_LTIPC
{
CLTIPCalc* calc = (CLTIPCalc*)ptr;
JNIUtil* util = new JNIUtil();
util->CopyArray(env, value, calc->m_adPctSharesVest);
}
i just want to copy the passed-in jdoubleArray to the member variable m_adPctSharesVest.
Sorry for the confusion.
>>>> Sorry for the confusion
No problem, but I need both the class/struct definition of CLTIPCalc and the code of JNIUtil::CopyArray.
You always should be aware that C++ needs allocation if handling with plain C arrays rather than with container classes.
Regards, Alex
No problem, but I need both the class/struct definition of CLTIPCalc and the code of JNIUtil::CopyArray.
You always should be aware that C++ needs allocation if handling with plain C arrays rather than with container classes.
Regards, Alex
ASKER
Definition of variable in CLTIPCalc:
double m_adPctSharesVest[11];
JNIUtil::CopyArray definitions:
//jdoubleArray to double[]
void JNIUtil::CopyArray(JNIEnv* env, jdoubleArray inObj, double* out)
{
jdouble* in = env->GetDoubleArrayElement s(inObj, FALSE);
int size = env->GetArrayLength(inObj) ;
if (size > 0)
{
out = new double[size];
for (int i = 0; i < size; i++)
out[i] = in[i];
}
else
out = NULL;
}
and then....
//double[] to jdoubleArray
jdoubleArray JNIUtil::CopyArray(JNIEnv* env, double* in, int size)
{
jdoubleArray out = env->NewDoubleArray(size);
env->SetDoubleArrayRegion( out, 0, size, in);
return out;
}
double m_adPctSharesVest[11];
JNIUtil::CopyArray definitions:
//jdoubleArray to double[]
void JNIUtil::CopyArray(JNIEnv*
{
jdouble* in = env->GetDoubleArrayElement
int size = env->GetArrayLength(inObj)
if (size > 0)
{
out = new double[size];
for (int i = 0; i < size; i++)
out[i] = in[i];
}
else
out = NULL;
}
and then....
//double[] to jdoubleArray
jdoubleArray JNIUtil::CopyArray(JNIEnv*
{
jdoubleArray out = env->NewDoubleArray(size);
env->SetDoubleArrayRegion(
return out;
}
>>>> void JNIUtil::CopyArray(JNIEnv* env, jdoubleArray inObj, double* out)
That is wrong cause we need to return 'out' pointer but were changing it locally only.
Either change to
void JNIUtil::CopyArray(JNIEnv* env, jdoubleArray inObj, double*& out)
Then out pointer was returned. Or - maybe better -
double* JNIUtil::CopyArray(JNIEnv* env, jdoubleArray inObj)
{
jdouble* in = env->GetDoubleArrayElement s(inObj, FALSE);
int size = env->GetArrayLength(inObj) ;
double out* = NULL;
if (size > 0)
{
out = new double[size];
for (int i = 0; i < size; i++)
out[i] = in[i];
}
return out;
}
Regards, Alex
That is wrong cause we need to return 'out' pointer but were changing it locally only.
Either change to
void JNIUtil::CopyArray(JNIEnv*
Then out pointer was returned. Or - maybe better -
double* JNIUtil::CopyArray(JNIEnv*
{
jdouble* in = env->GetDoubleArrayElement
int size = env->GetArrayLength(inObj)
double out* = NULL;
if (size > 0)
{
out = new double[size];
for (int i = 0; i < size; i++)
out[i] = in[i];
}
return out;
}
Regards, Alex
correction:
I saw that you already have an allocation for the double array. So, you could change the code to
jdoubleArray to double[]
void JNIUtil::CopyArray(JNIEnv* env, jdoubleArray inObj, double* out)
{
jdouble* in = env->GetDoubleArrayElement s(inObj, FALSE);
int size = env->GetArrayLength(inObj) ;
if (size > 0 && size <= 11)
{
for (int i = 0; i < size; i++)
out[i] = in[i];
}
}
Returning a pointer is senseful only if you would change the array in the struct CLTIPCalc to a pointer initialized by NULL. Then, you would call like
calc->m_adPctSharesVest = util->CopyArray(env, value );
Regards, Alex
I saw that you already have an allocation for the double array. So, you could change the code to
jdoubleArray to double[]
void JNIUtil::CopyArray(JNIEnv*
{
jdouble* in = env->GetDoubleArrayElement
int size = env->GetArrayLength(inObj)
if (size > 0 && size <= 11)
{
for (int i = 0; i < size; i++)
out[i] = in[i];
}
}
Returning a pointer is senseful only if you would change the array in the struct CLTIPCalc to a pointer initialized by NULL. Then, you would call like
calc->m_adPctSharesVest = util->CopyArray(env, value );
Regards, Alex
>>>> Definition of variable in CLTIPCalc:
>>>> double m_adPctSharesVest[11];
Did you initialize the array somehow? You could do it in a constructor:
CLTIPCalc::CLTIPCalc()
{
memset(m_adPctSharesVest, 0, sizeof(m_adPctSharesVest)) ;
// init other members or use an initialiser list
}
Or - maybe simpler - initialize the struct when creating an instance:
CLTIPCalc any = { 0 }; // make all zero
Note, that can't be done if there are class members.
Regards, Alex
>>>> double m_adPctSharesVest[11];
Did you initialize the array somehow? You could do it in a constructor:
CLTIPCalc::CLTIPCalc()
{
memset(m_adPctSharesVest, 0, sizeof(m_adPctSharesVest))
// init other members or use an initialiser list
}
Or - maybe simpler - initialize the struct when creating an instance:
CLTIPCalc any = { 0 }; // make all zero
Note, that can't be done if there are class members.
Regards, Alex
ASKER
it is initialized as a static array in the header file: double m_adPctSharesVest[11];
ASKER
Seems OK, I ended up using a solution not posted here. Thank you.
>>>> Seems OK, I ended up using a solution not posted here. Thank you.
I made at least 6 comments with valid C++ code responding to various additional questions made by jsm11482.
If the questioner doesn't honour that, I don't want points, but a refund isn't appropriate, especially as there is no open question left - as far as I can see.
Regards, Alex
I made at least 6 comments with valid C++ code responding to various additional questions made by jsm11482.
If the questioner doesn't honour that, I don't want points, but a refund isn't appropriate, especially as there is no open question left - as far as I can see.
Regards, Alex
ASKER
I am trying out your other code changes and will get back to you!
Thanks!