From: Gibbs, S. <Sol...@sr...> - 2007-12-19 15:11:35
|
Hello, =20 I hope this isn't an obvious question, but I have looked through the docs and I can't figure it out. =20 I'm exporting an existing C library to Java. I have a C struct along the lines of: typedef=20 struct { char* next_in; unsigned int avail_in; =20 char* next_out; unsigned int avail_out; =20 } bz_stream; =20 bz_stream gets wrapped with a Java proxy class, and I can specify a C-method for backing the constructor with the %extend directive. Since the library functions as a stream filter, I allocate heap space in Java using two direct Java NIO Buffers and override %typemap(in) char* and %typemap(memberin) char* so that the setter method on the bz_stream proxy class sets the bz_stream->next_in and next_out as the address of the direct Buffer. =20 There are two problems with this: Because the proxy class only retains a reference to the underlying array and not the actual Java Buffer object, there is the potential for the Buffer to be garbage collected prematurely. In addition, the getter generated for the bz_stream proxy makes no sense, because it cannot return the Buffer object. =20 How do I modify the proxy code for the setters to retain a reference to the Buffer object and the code for the getters to return that reference? =20 As a matter of style and productivity, is it better to spend time fixing up the proxy classes to present a clean interface, or should I just plan on having a somewhat messy boundary layer between Java and C and try to smooth it out by adding a layer of abstraction in Java? =20 - Solomon |
From: William S F. <ws...@fu...> - 2007-12-22 11:18:48
|
Gibbs, Solomon wrote: > Hello, > > I hope this isn't an obvious question, but I have looked through the > docs and I can't figure it out. > > I'm exporting an existing C library to Java. I have a C struct along the > lines of: > typedef > struct { > char* next_in; > unsigned int avail_in; > > char* next_out; > unsigned int avail_out; > > } bz_stream; > > bz_stream gets wrapped with a Java proxy class, and I can specify a > C-method for backing the constructor with the %extend directive. Since > the library functions as a stream filter, I allocate heap space in Java > using two direct Java NIO Buffers and override %typemap(in) char* and > %typemap(memberin) char* so that the setter method on the bz_stream > proxy class sets the bz_stream->next_in and next_out as the address of > the direct Buffer. > > There are two problems with this: Because the proxy class only retains a > reference to the underlying array and not the actual Java Buffer object, > there is the potential for the Buffer to be garbage collected > prematurely. In addition, the getter generated for the bz_stream proxy > makes no sense, because it cannot return the Buffer object. > > > How do I modify the proxy code for the setters to retain a reference to > the Buffer object and the code for the getters to return that reference? > Use the same techniques as outlined here: http://www.swig.org/Doc1.3/Java.html#java_memory_management_member_variables > > As a matter of style and productivity, is it better to spend time fixing > up the proxy classes to present a clean interface, or should I just plan > on having a somewhat messy boundary layer between Java and C and try to > smooth it out by adding a layer of abstraction in Java? > Unless you have many similar types of structs, I would write an abstraction layer with a pure Java wrapper class which manages the memory references. It would wrap the SWIG generated proxy. You could squeeze this functionality into the proxy class, but it requires a lot of messing around with typemaps and features and will take someone not familiar with SWIG somewhat longer to do. William |