Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #25230 > unrolled thread
| Started by | "Borneq" <borneq@antyspam.hidden.pl> |
|---|---|
| First post | 2013-09-05 17:05 +0200 |
| Last post | 2013-09-19 15:02 +0100 |
| Articles | 14 — 4 participants |
Back to article view | Back to comp.lang.java.programmer
JNI and GetFieldID "Borneq" <borneq@antyspam.hidden.pl> - 2013-09-05 17:05 +0200
Re: JNI and GetFieldID Mark <i@dontgetlotsofspamanymore.invalid> - 2013-09-06 10:25 +0100
Re: JNI and GetFieldID Steven Simpson <ss@domain.invalid> - 2013-09-06 16:36 +0300
Re: JNI and GetFieldID "Borneq" <borneq@antyspam.hidden.pl> - 2013-09-06 18:53 +0200
Re: JNI and GetFieldID "Borneq" <borneq@antyspam.hidden.pl> - 2013-09-06 20:44 +0200
Re: JNI and GetFieldID Steven Simpson <ss@domain.invalid> - 2013-09-06 22:34 +0300
Re: JNI and GetFieldID "Borneq" <borneq@antyspam.hidden.pl> - 2013-09-06 23:06 +0200
Re: JNI and GetFieldID "Borneq" <borneq@antyspam.hidden.pl> - 2013-09-07 22:27 +0200
Re: JNI and GetFieldID Steven Simpson <ss@domain.invalid> - 2013-09-08 10:24 +0100
Re: JNI and GetFieldID "Borneq" <borneq@antyspam.hidden.pl> - 2013-09-08 12:29 +0200
Re: JNI and GetFieldID "Borneq" <borneq@antyspam.hidden.pl> - 2013-09-08 22:45 +0200
Re: JNI and GetFieldID Steven Simpson <ss@domain.invalid> - 2013-09-13 13:31 +0100
Re: JNI and GetFieldID "Borneq" <borneq@antyspam.hidden.pl> - 2013-09-14 18:50 +0200
Re: JNI and GetFieldID "Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org> - 2013-09-19 15:02 +0100
| From | "Borneq" <borneq@antyspam.hidden.pl> |
|---|---|
| Date | 2013-09-05 17:05 +0200 |
| Subject | JNI and GetFieldID |
| Message-ID | <l0a6jn$9t4$1@node1.news.atman.pl> |
I have class:
package net.sf.junace;
public class ACEList {
ACEFiles files; // specifies files to be listed;
byte[] reserved; // 64 bytes has to be filled with zeroes
}
I call native :
ACEList aaa = new ACEList();
unACE.nativeACEList("abc", aaa);
in c++ is:
JNIEXPORT void JNICALL Java_net_sf_junace_UnACE_nativeACEList
(JNIEnv *env, jobject jObj1, jstring archiveName, jobject jObj2)
which field I must read?
jclass cls1 = env->GetObjectClass(jObj1);
or
jclass cls2 = env->GetObjectClass(jObj2);
?
jfieldID fid = env->GetFieldID(cls1 or cls2, "something",
"Lnet/sf/junace/ACEList;");
what I must choose cls1 or cls2
what I must pass as second argument as "something"?
[toc] | [next] | [standalone]
| From | Mark <i@dontgetlotsofspamanymore.invalid> |
|---|---|
| Date | 2013-09-06 10:25 +0100 |
| Message-ID | <gr7j29ll8v8ciaibmhoqrrqqtjf3817knq@4ax.com> |
| In reply to | #25230 |
On Thu, 5 Sep 2013 17:05:26 +0200, "Borneq"
<borneq@antyspam.hidden.pl> wrote:
>I have class:
>package net.sf.junace;
>public class ACEList {
>ACEFiles files; // specifies files to be listed;
>byte[] reserved; // 64 bytes has to be filled with zeroes
>}
>I call native :
>ACEList aaa = new ACEList();
>unACE.nativeACEList("abc", aaa);
>
>in c++ is:
>JNIEXPORT void JNICALL Java_net_sf_junace_UnACE_nativeACEList
>(JNIEnv *env, jobject jObj1, jstring archiveName, jobject jObj2)
>which field I must read?
>jclass cls1 = env->GetObjectClass(jObj1);
>or
>jclass cls2 = env->GetObjectClass(jObj2);
>?
>jfieldID fid = env->GetFieldID(cls1 or cls2, "something",
>"Lnet/sf/junace/ACEList;");
>what I must choose cls1 or cls2
>what I must pass as second argument as "something"?
It depends on what you are trying to do. Can you post a complete
(small) example?
--
(\__/) M.
(='.'=) If a man stands in a forest and no woman is around
(")_(") is he still wrong?
[toc] | [prev] | [next] | [standalone]
| From | Steven Simpson <ss@domain.invalid> |
|---|---|
| Date | 2013-09-06 16:36 +0300 |
| Message-ID | <gb2pfa-s33.ln1@s.simpson148.btinternet.com> |
| In reply to | #25230 |
On 05/09/13 18:05, Borneq wrote:
> I have class:
[Some spacing added.]
package net.sf.junace;
public class ACEList {
ACEFiles files; // specifies files to be listed;
byte[] reserved; // 64 bytes has to be filled with zeroes
}
> I call native :
> ACEList aaa = new ACEList();
> unACE.nativeACEList("abc", aaa);
> in c++ is:
> JNIEXPORT void JNICALL Java_net_sf_junace_UnACE_nativeACEList
> (JNIEnv *env, jobject jObj1, jstring archiveName, jobject jObj2)
'jObj1' corresponds to 'this', i.e. 'unACE'. 'archiveName' will be
"abc". 'jObj2' corresponds to 'aaa'.
> which field I must read?
> jclass cls1 = env->GetObjectClass(jObj1);
> or
> jclass cls2 = env->GetObjectClass(jObj2);
> ?
> jfieldID fid = env->GetFieldID(cls1 or cls2, "something",
> "Lnet/sf/junace/ACEList;");
> what I must choose cls1 or cls2
Since you don't say much about what type 'unACE' is, I assume you want
to access a field of 'aaa', whose type is ACEList. You could probably
get it from cls2, but that is the class of the object, which could be
ACEList or a subtype. I think you want to get the jclass for ACEList
directly, so perhaps:
jclass cls = env->FindClass("net/sf/junace/ACEList");
> what I must pass as second argument as "something"?
<http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp16536>
It says that the string is the name of the field, so either "files" or
"reserved".
But I think your last argument is wrong. It should be the type
signature of the field. If you want the field 'files', and assuming
that ACEFiles is in the same package as ACEList, you want
"Lnet/sf/junace/ACEFiles;". If you want the field 'reserved', the type
signature is "[B".
--
ss at comp dot lancs dot ac dot uk
[toc] | [prev] | [next] | [standalone]
| From | "Borneq" <borneq@antyspam.hidden.pl> |
|---|---|
| Date | 2013-09-06 18:53 +0200 |
| Message-ID | <l0d1ak$5s5$1@node1.news.atman.pl> |
| In reply to | #25233 |
User "Steven Simpson" <ss@domain.invalid>> jclass cls =
env->FindClass("net/sf/junace/ACEList");
Thanks,
User "Mark" <i@dontgetlotsofspamanymore.invalid> > It depends on what you
are trying to do. Can you post a complete
> (small) example?
Expecially I want work with callbacks. I have written simple working demo:
=======> https://github.com/borneq/JNIdemo
for example here is:
jclass cls = env->GetObjectClass(param1);
jmethodID mid = env->GetMethodID(cls, "OnPercent", "(I)V");
My little puropose: expanding this example to callbacks with params, where
params can be class, for example:
=======> https://gist.github.com/borneq/6462783
void OnPercentEx(CmplxStruct cs);
[toc] | [prev] | [next] | [standalone]
| From | "Borneq" <borneq@antyspam.hidden.pl> |
|---|---|
| Date | 2013-09-06 20:44 +0200 |
| Message-ID | <l0d7po$cqp$1@node1.news.atman.pl> |
| In reply to | #25234 |
Użytkownik "Borneq" <borneq@antyspam.hidden.pl> napisał w wiadomości
news:l0d1ak$5s5$1@node1.news.atman.pl...
> =======> https://github.com/borneq/JNIdemo
> =======> https://gist.github.com/borneq/6462783
public interface ICallback {
void OnPercent(int percent);
void OnPercentEx(CmplxStruct cs);
}
public class CmplxStruct {
int fieldI;
String str;
}
How place number and string?
jmethodID mid;
mid = env->GetMethodID(cls, "OnPercentEx", "(LCmplxStruct;)V");
env->CallVoidMethod(param1, mid, SOMETHING);
how fill SOMETHING?
[toc] | [prev] | [next] | [standalone]
| From | Steven Simpson <ss@domain.invalid> |
|---|---|
| Date | 2013-09-06 22:34 +0300 |
| Message-ID | <8bnpfa-417.ln1@s.simpson148.btinternet.com> |
| In reply to | #25235 |
On 06/09/13 21:44, Borneq wrote:
> public interface ICallback {
> void OnPercent(int percent);
> void OnPercentEx(CmplxStruct cs);
> }
While in Java, you should use Java conventions, e.g. onPercent for a
method name. Can't say I'm a fan of prefixing "Callback" with "I" to
show it's an interface either.
> public class CmplxStruct {
> int fieldI;
> String str;
> }
CmplxStruct? Ky, 'll tk tht s jst n ex.
> How place number and string?
> jmethodID mid;
> mid = env->GetMethodID(cls, "OnPercentEx", "(LCmplxStruct;)V");
> env->CallVoidMethod(param1, mid, SOMETHING);
> how fill SOMETHING?
Never learned to do that - looks too error-prone. Instead of mucking
around in JNI, creating objects, accessing fields, etc, I prefer to do
as much as I can in Java, then declare the native methods as taking the
already dismantled fields as separate arguments.
You could do similar for a callback. Write a private static method to
do the fiddly stuff:
private static void callBack(ICallback dest, int i, String s) {
CmplxStruct obj = new CmplxStruct();
obj.fieldI = i;
obj.str = s;
dest.OnPercentEx(obj);
}
Now, in JNI, you use something like:
jobject dest = ...;
jint i = ...;
jstring s = ...;
mid = env->GetStaticMethodID(cls, "callBack", "(LICallback;ILjava/lang/String;)V");
env->CallStaticVoidMethod(dest, i, s);
--
ss at comp dot lancs dot ac dot uk
[toc] | [prev] | [next] | [standalone]
| From | "Borneq" <borneq@antyspam.hidden.pl> |
|---|---|
| Date | 2013-09-06 23:06 +0200 |
| Message-ID | <l0dg42$lbe$1@node1.news.atman.pl> |
| In reply to | #25236 |
Użytkownik "Steven Simpson" <ss@domain.invalid> napisał w wiadomości
news:8bnpfa-417.ln1@s.simpson148.btinternet.com...
> Never learned to do that - looks too error-prone. Instead of mucking
> around in JNI, creating objects, accessing fields, etc, I prefer to do as
> much as I can in Java, then declare the native methods as taking the
> already dismantled fields as separate arguments.
But this is difficult, because I want to write JNI wrapper to UnACE -
library for expanding .ace archives.
There are callbacks like
INT (__stdcall *StateCallbackProc)
(pACEStateCallbackProcStruc State);
where
typedef union sACEStateCallbackProcStruc
*pACEStateCallbackProcStruc;
typedef union sACEStateCallbackProcStruc
{
ULONG StructureType; // indicates which of the
fol-
// lowing structures is used
tACECallbackArchiveStruc Archive;
tACECallbackArchivedFileStruc ArchivedFile;
tACECallbackRealFileStruc RealFile;
tACECallbackProgressStruc Progress;
tACECallbackCRCCheckStruc CRCCheck;
} tACEStateCallbackProcStruc;
where for example:
typedef struct sACECallbackArchiveStruc
{
ULONG StructureType; // is ACE_CALLBACK_TYPE_ARCHIVE
ULONG Code; // see definition of
// ACE_CALLBACK_TYPE_ARCHIVE
ULONG Operation; // ACE_CALLBACK_OPERATION constant
pACEGlobalDataStruc GlobalData; // see tACEGlobalDataStruc
pACEArchiveDataStruc ArchiveData; // see tACEArchiveDataStruc
} tACECallbackArchiveStruc,
*pACECallbackArchiveStruc;
There are structures reference inside other structures
[toc] | [prev] | [next] | [standalone]
| From | "Borneq" <borneq@antyspam.hidden.pl> |
|---|---|
| Date | 2013-09-07 22:27 +0200 |
| Message-ID | <l0g277$75f$1@node1.news.atman.pl> |
| In reply to | #25234 |
Użytkownik "Borneq" <borneq@antyspam.hidden.pl> napisał w wiadomości news:l0d1ak$5s5$1@node1.news.atman.pl... > =======> https://github.com/borneq/JNIdemo Main problem: in this demo callback is not called by pointer to function but only CallVoidMethod. But my library must be above other library which uses callback by pointer to function. How do it?
[toc] | [prev] | [next] | [standalone]
| From | Steven Simpson <ss@domain.invalid> |
|---|---|
| Date | 2013-09-08 10:24 +0100 |
| Message-ID | <7cstfa-3nc.ln1@s.simpson148.btinternet.com> |
| In reply to | #25240 |
On 07/09/13 21:27, Borneq wrote:
> Użytkownik "Borneq" <borneq@antyspam.hidden.pl> napisał w wiadomości
> news:l0d1ak$5s5$1@node1.news.atman.pl...
>> =======> https://github.com/borneq/JNIdemo
>
> Main problem: in this demo callback is not called by pointer to
> function but only CallVoidMethod. But my library must be above other
> library which uses callback by pointer to function. How do it?
If the callbacks are C, they will usually have a (void *) parameter to
pass context. (If they don't, I'd say they're shoite, or they're not
what one supposes they're for.) The context will have to include the
JNIEnv pointer at least, and the details of the Java callback.
Suppose that the library you're wrapping defines a callback:
typedef void foo_callback1(void *, int, const char *);
void foo_do_something(foo_obj *, foo_callback1 *cb, void *ctxt);
In Java, you define a corresponding callback interface:
package foo;
interface Callback1 {
void apply(int x, String s);
}
class Foo {
native void doSomething(Callback1 cb);
}
Back in C, you write a C callback which invokes a Java callback:
struct this_op_context {
JNIEnv *env;
jobject user;
};
static void my_callback(void *vctxt, int x, const char *s)
{
struct this_op_context *ctxt = vctxt;
jstring str = ctxt->env->NewStringUTF(s);
jclass cls = ctxt->env->FindClass("foo/Callback1");
jmethodID mid = ctxt->env->GetMethodID(cls, "apply", "(ILjava/lang/String;)V");
ctxt->env->CallVoidMethod(env->user, (jint) x, str);
// Clean up?
...
}
...and set it up to be invoked:
JNIEXPORT void JNICALL Java_foo_Foo_doSomething
(JNIEnv *env, jobject jObj1, jobject cb)
{
struct this_op_context ctxt = {
.env = env,
.user = cb;
};
// Extract/create foo structures from data in jObj1.
foo_obj *foo = ...;
foo_do_something(foo, &my_callback, &ctxt);
// Clean up?
...
}
That's assuming you don't need any C foo structures to persist beyond
this call, and no callback will occur after foo_do_something has
returned. Otherwise, you have to start thinking about memory management
of the foo structures and the callback contexts, and whether you want
them to map to Java objects, and how to do that mapping, etc.
I can think of straight-forward ways to map (say) a foo.Foo to a
foo_obj, but I'm not so sure about how you'd manage a struct
this_op_context. I'd also be concerned about whether the JNIEnv pointer
stored in the struct was even valid after returning from the native call.
--
ss at comp dot lancs dot ac dot uk
[toc] | [prev] | [next] | [standalone]
| From | "Borneq" <borneq@antyspam.hidden.pl> |
|---|---|
| Date | 2013-09-08 12:29 +0200 |
| Message-ID | <l0hjht$nvr$1@node1.news.atman.pl> |
| In reply to | #25244 |
Użytkownik "Steven Simpson" <ss@domain.invalid> napisał w wiadomości news:7cstfa-3nc.ln1@s.simpson148.btinternet.com... > If the callbacks are C, they will usually have a (void *) parameter to > pass context. (If they don't, I'd say they're shoite, or they're not what > one supposes they're for.) The context will have to include the JNIEnv > pointer at least, and the details of the Java callback. > > Suppose that the library you're wrapping defines a callback: > > typedef void foo_callback1(void *, int, const char *); > void foo_do_something(foo_obj *, foo_callback1 *cb, void *ctxt); Thanks for answer and examples ;-) I want wrap library UnAceV2.dll which is provided without sources. (http://www.winace.com/) I can't change foo_callback and foo_do_something parameters. The callback function is INT __stdcall StateProc(pACEStateCallbackProcStruc State) the do_something function is INT __stdcall ACEListProc(LPSTR ArchiveName, pACEListStruc List); Inside StateProc I can call my_callback function, and ACEListProc will be called inside native function. Native function can store env and others parameters. But how within StateProc refer to this env and other parameters? This parameters must be stored globally in data segment?
[toc] | [prev] | [next] | [standalone]
| From | "Borneq" <borneq@antyspam.hidden.pl> |
|---|---|
| Date | 2013-09-08 22:45 +0200 |
| Message-ID | <l0inlt$er4$1@node2.news.atman.pl> |
| In reply to | #25245 |
Użytkownik "Borneq" <borneq@antyspam.hidden.pl> napisał w wiadomości news:l0hjht$nvr$1@node1.news.atman.pl... > Inside StateProc I can call my_callback function, and ACEListProc will be > called inside native function. Native function can store env and others > parameters. But how within StateProc refer to this env and other > parameters? This parameters must be stored globally in data segment? My last demo: https://github.com/borneq/JNIdemo
[toc] | [prev] | [next] | [standalone]
| From | Steven Simpson <ss@domain.invalid> |
|---|---|
| Date | 2013-09-13 13:31 +0100 |
| Message-ID | <d5dbga-em5.ln1@s.simpson148.btinternet.com> |
| In reply to | #25245 |
On 08/09/13 11:29, Borneq wrote: > Inside StateProc I can call my_callback function, and ACEListProc will > be called inside native function. Native function can store env and > others parameters. But how within StateProc refer to this env and > other parameters? It's a bugger, isn't it?! > This parameters must be stored globally in data segment? Perhaps. This option would need some synchronization on the Java side to protect it, but I'm not sure that would suffice in some cases (e.g., when the class you lock on is loaded multiple times). A thread-local in C? Find out what the JVM uses for threads, and use its thread-local feature. Perhaps you can use the C callback just to build up a structure locally. When control returns from the library back to your JNI function, you iterate over the structure to invoke Java callbacks. I'm out of decent ideas. -- ss at comp dot lancs dot ac dot uk
[toc] | [prev] | [next] | [standalone]
| From | "Borneq" <borneq@antyspam.hidden.pl> |
|---|---|
| Date | 2013-09-14 18:50 +0200 |
| Message-ID | <l1243u$iqk$1@node1.news.atman.pl> |
| In reply to | #25280 |
Użytkownik "Steven Simpson" <ss@domain.invalid> napisał w wiadomości news:d5dbga-em5.ln1@s.simpson148.btinternet.com... > A thread-local in C? Find out what the JVM uses for threads, and use its > thread-local feature. __declspec(thread) struct sJniHandle jniHandle; in Visual Studio 2010?
[toc] | [prev] | [next] | [standalone]
| From | "Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org> |
|---|---|
| Date | 2013-09-19 15:02 +0100 |
| Message-ID | <ptqdnfE0Qp55nqbPnZ2dnUVZ7tSdnZ2d@bt.com> |
| In reply to | #25280 |
Steven Simpson wrote:
> On 08/09/13 11:29, Borneq wrote:
> > Inside StateProc I can call my_callback function, and ACEListProc will
> > be called inside native function. Native function can store env and
> > others parameters. But how within StateProc refer to this env and
> > other parameters?
>
> It's a bugger, isn't it?!
I think what you (plural) are looking for is the GetEnv() function, or the
(JavaVM::GetEnv() method). That will return the correct JNIEnv to use in
whatever context you call it. If there already is a JNIEnv that can be validly
used in that context then the operation is cheap. If not then the operation is
a bit more expensive, but necessary and so unavoidable.
If you are dealing with callbacks that might not happen on a thread that's
known to Java (improbable in this case) then you'd better look into
AttachCurrentThread() and DetachCurrentThread() too.
If the main program is a Java program (rather than a C/C++/whatever program
that uses Java via JNI) then you won't naturally have a reference to a JavaVM.
You can find that from any handy JNIEnv with GetJavaVM(). The JavaVM is a
globally shared, and unique, object, so it can be treated as threadsafe (there
may be documented exceptions to that -- I no longer remember clearly), and so
it's OK to put a reference to it into some shared global variable at the C/C++
level.
-- chris
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web