简体   繁体   中英

Use extensive c++ library with JNI with non-primitive arguments

I have an application I've written in Java and I have a c++ library for triangulation (source code given here: http://graphics.ucmerced.edu/software/tripath/index.html ) that I'd like to be able to use with JNI. The library is basically creating a triangulation out of points and edges you give it. You initialize the class with the starting information of the "space" and call functions to modify your triangulation. Finally, you can access the points and edges using a getter that takes pointers to arrays as parameters. I want to be able to call these functions, and store the relevant information in Java objects from classes I've defined.

I've never used JNI before so I'm very new to this and it looks incredibly complex. The Oracle introduction and explanation is incredibly detailed and lengthy and all the tutorials I've found aren't suitable for my needs. Every tutorial I've looked at has only discussed using primitives and arrays in JNI as parameters and return types, but I have no idea how to deal with more complex issues.

Can anyone explain how to create JNI code that provides a wrapper for complicated functions using c++ class as parameters and return types? If you could also link to an informative tutorial, that would be wonderful.

Here's some excerpts from the class I'm dealing with if you want to get a better idea for the problem. If you need any more information, I can either post code or you can download the source code from the link i posted. Thanks!

void SeDcdt::get_mesh_edges ( GsArray<GsPnt2>* constr, GsArray<GsPnt2>* unconstr )
 {
   SeDcdtEdge *e, *ei;
   SeDcdtSymEdge *s;
   GsArray<GsPnt2>* pa;

   if ( constr ) constr->size(0);
   if ( unconstr ) unconstr->size(0);

   e = ei = mesh()->first()->edg();

   do { if ( e->is_constrained() ) pa=constr; else pa=unconstr;
        if ( pa )
         { s = e->se();  pa->push() = s->vtx()->p;
           s = s->nxt(); pa->push() = s->vtx()->p;
         }
        e = e->nxt();
      } while ( e!=ei );
 }

int SeDcdt::insert_polygon ( const GsPolygon& pol )
 {
   int i, i1, id;
   SeVertex* v;
   SeFace* sface;

   _dcdt_changed = true;

   GS_TRACE1 ( "Inserting entry in the polygon set..." ); // put in _polygons
   id = _polygons.insert();
   InsPol& ip = *_polygons[id];
   ip.open = pol.open();

   GS_TRACE1 ( "Inserting polygon points..." ); // insert vertices
   sface = get_search_face();
   for ( i=0; i<pol.size(); i++ )
    { v = SeTriangulator::insert_point ( pol[i].x, pol[i].y, sface );
      if ( !v ) gsout.fatal ( "se_dcdt.cpp: search failure in _insert_polygon()." );
      ip.push() = (SeDcdtVertex*)v;
      sface = v->se()->fac();
    }

   // should we keep here collinear vertices (which are not corners)? 
   // they can be removed as Steiner vertices when removing another intersecting polygon

   _cur_search_face=0; // Needed because edge constraint may call kef

   GS_TRACE1 ( "Inserting polygon edges constraints..." ); // insert edges
   for ( i=0; i<ip.size(); i++ )
    { i1 = (i+1)%ip.size();
      if ( i1==0 && ip.open ) break; // do not close the polygon
      if ( !SeTriangulator::insert_line_constraint ( ip[i], ip[i1], id ) ) 
        gsout.fatal ( "se_dcdt.cpp: unable to insert constraint in _insert_polygon()." );
    }

   return id;
 }

In the nutshell, you should choose the JNI layer to suit your application best. Keep in mind that switching context from Java to C++ and vice versa may have significant overhead. Conversion of complex objects from one realm to the other is expensive, too. Therefore it is preferable to keep as much data as possible encapsulated in C++, and keep the JNI calls to minimum.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM