问题
How would you configure the SWIG .i file to handle the C FILE * type? The below function sets a file so that log output can be written to it. I need to call if from a Java class. Currently a public static void setLogFile(SWIGTYPE_p_FILE fd) function is generated by SWIG when I just include the C header file with the below function. Any ideas?
C Function:
void setLogFile(FILE *fd);
I attempted #1 using the below and got the below exception:
test.i:
%module Example
%{
#include "headerLogFile.h"
%}
%inline %{
void setLogFile(const char *fn) {
FILE *f = fopen(fn, "w");
setLogFile(f);
}
%}
%ignore setLogFile;
%include "headerLogFile.h"
Exception:
[exec] test_wrap.c:193: error: conflicting types for 'setLogFile'
[exec] /test/include/headerLogFile.h:96: error: previous declaration of 'setLogFile' was here
[exec] test_wrap.c: In function `setLogFile':
[exec] test_wrap.c:195: warning: passing arg 1 of `setLogFile' from incompatible pointer type
回答1:
Given test.h which looks like:
#include <stdio.h>
inline void setLogFile(FILE *fd) {
fprintf(fd, "Test\n");
fflush(fd);
}
I can see three approaches you might chose to take to wrapping this function:
Method 1 - Pass a String
from Java:
Expose a function to Java that expects a file name passed as a String
, not a FILE*
:
%module method1
%{
#include "test.h"
%}
%inline %{
void setLogFile(const char *fn) {
FILE *f = fopen(fn, "w");
setLogFile(f);
}
%}
This uses %inline
to instruct SWIG to wrap this function at the same time as defining it. If you still use %include "test.h"
then you'd probably want to hide the original version from SWIG.
Method 2 - Wrap more of stdio.h:
Wrap more than just setLogFile
, wrap things like fopen
, fmemopen
etc. as appropriate. (I don't like this solution much personally so I've not made an example for it)
Method 3 - Expose a Java interface that takes a FileOutputStream:
%module method3
%{
#include "test.h"
#include <cassert>
%}
// 3:
%typemap(jni) FILE *fd "jobject"
// 1:
%typemap(jstype) FILE *fd "java.io.FileOutputStream"
// 2:
%typemap(jtype) FILE *fd "java.io.FileDescriptor"
// 4:
%typemap(in) (FILE *fd) {
jfieldID field_fd;
jclass class_fdesc;
int rawfd;
class_fdesc = jenv->FindClass("java/io/FileDescriptor");
assert(class_fdesc);
field_fd = jenv->GetFieldID(class_fdesc, "fd", "I");
assert(field_fd);
rawfd = jenv->GetIntField($input, field_fd);
$1 = fdopen(rawfd, "w");
// Add some code to throw a Java exception if $1 is NULL (i.e. error)
}
// 5:
%typemap(javain, pre=" retainFD = $javainput;",
throws="java.io.IOException") FILE *fd "$javainput.getFD()"
// 6:
%pragma(java) modulecode=%{
private static java.io.FileOutputStream retainFD;
%}
%include "test.h"
This does the following things:
- We want the input to the actual public part of the module to be
java.io.FileOutputStream
. - The the Java side of the JNI code is going to take a
java.io.FileDescriptor
instead however. - The C++ side of the JNI code is going to see this as a
jobject
- On the C++ side we're going to do something that's a little evil - read a private
int
field in theFileDescriptor
class (see here). This is probably not portable and reading private parts of classes is generally considered bad, but it allows us to get something we can pass tofdopen()
to get aFILE*
for the "real" call - Mostly this typemap takes the
FileOutputStream
and callsgetFD()
on it to get theFileDescriptor
object for it. It also adds an exception specification to matchgetFD()
and performs one other function which is part of the next point - We need to be sure that Java won't garbage collect and finalize the
FileOutputStream
, which would close the file handle and invalidate ourFILE*
. We do this by keeping a reference to theFileOutputStream
we were given in aprivate static
variable. Thepre="...
of the previous typemap causes the most recent one to be retained until we change to another one. (If we do callsetLogFile
twice it's OK and in fact good that we release our reference to the previousFileOutputStream
)
来源:https://stackoverflow.com/questions/8320605/swig-configuration-to-handle-a-file-c-input-parameter-in-java