如何配置SWIG .i文件来处理C FILE *类型?下面的函数设置一个文件,以便可以将日志输出写入它。我需要从Java类调用。目前,当我只包含带有以下函数的C头文件时,SWIG会生成一个公共静态void setLogFile(SWIGTYPE_p_FILE fd)函数。有任何想法吗?
C函数:
void setLogFile(FILE *fd);
我使用下面的方法尝试了#1并获得了以下例外:
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"
例外:
[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
答案 0 :(得分:2)
给出test.h看起来像:
#include <stdio.h>
inline void setLogFile(FILE *fd) {
fprintf(fd, "Test\n");
fflush(fd);
}
我可以看到你可以选择采用三种方法来包装这个功能:
String
:向Java公开一个函数,希望文件名作为String
传递,而不是FILE*
:
%module method1
%{
#include "test.h"
%}
%inline %{
void setLogFile(const char *fn) {
FILE *f = fopen(fn, "w");
setLogFile(f);
}
%}
这使用%inline
指示SWIG在定义此函数的同时包装此函数。如果你仍然使用%include "test.h"
,那么你可能想要hide the original version from SWIG。
包裹的不只是setLogFile
,请根据需要包含fopen
,fmemopen
等内容。 (我不太喜欢这个解决方案,所以我没有为它做出一个例子)
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"
这可以做到以下几点:
java.io.FileOutputStream
。java.io.FileDescriptor
。jobject
int
类(see here)中的私有FileDescriptor
字段。这可能是不可移植的,阅读私有部分的课程通常被认为是不好的,但它允许我们得到一些我们可以传递给fdopen()
以获得FILE*
“真实”电话的内容FileOutputStream
并在其上调用getFD()
来获取FileDescriptor
对象。它还添加了一个匹配getFD()
的异常规范,并执行另一个函数,它是下一个点的一部分FileOutputStream
,这将关闭文件句柄并使FILE*
无效。我们通过保留对FileOutputStream
变量中给出的private static
的引用来实现此目的。前一个typemap的pre="...
会导致保留最新的一个,直到我们更改为另一个。 (如果我们两次调用setLogFile
就可以了,事实上我们发布了对前一个FileOutputStream
的引用