Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #25230 > unrolled thread

JNI and GetFieldID

Started by"Borneq" <borneq@antyspam.hidden.pl>
First post2013-09-05 17:05 +0200
Last post2013-09-19 15:02 +0100
Articles 14 — 4 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  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

#25230 — JNI and GetFieldID

From"Borneq" <borneq@antyspam.hidden.pl>
Date2013-09-05 17:05 +0200
SubjectJNI 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]


#25232

FromMark <i@dontgetlotsofspamanymore.invalid>
Date2013-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]


#25233

FromSteven Simpson <ss@domain.invalid>
Date2013-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]


#25234

From"Borneq" <borneq@antyspam.hidden.pl>
Date2013-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]


#25235

From"Borneq" <borneq@antyspam.hidden.pl>
Date2013-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]


#25236

FromSteven Simpson <ss@domain.invalid>
Date2013-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]


#25237

From"Borneq" <borneq@antyspam.hidden.pl>
Date2013-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]


#25240

From"Borneq" <borneq@antyspam.hidden.pl>
Date2013-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]


#25244

FromSteven Simpson <ss@domain.invalid>
Date2013-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]


#25245

From"Borneq" <borneq@antyspam.hidden.pl>
Date2013-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]


#25262

From"Borneq" <borneq@antyspam.hidden.pl>
Date2013-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]


#25280

FromSteven Simpson <ss@domain.invalid>
Date2013-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]


#25287

From"Borneq" <borneq@antyspam.hidden.pl>
Date2013-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]


#25305

From"Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org>
Date2013-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