在Java中处理FILE*C输入参数的SWIG配置
如何配置SWIG.i文件来处理C文件*类型?下面的函数设置一个文件,以便可以将日志输出写入其中。我需要从Java类调用if。目前,当我只使用下面的函数包含C头文件时,SWIG生成了一个公共静态void setLogFile(SWIGTYPE_p_FILE fd)函数。有什么想法吗 C功能:在Java中处理FILE*C输入参数的SWIG配置,java,swig,Java,Swig,如何配置SWIG.i文件来处理C文件*类型?下面的函数设置一个文件,以便可以将日志输出写入其中。我需要从Java类调用if。目前,当我只使用下面的函数包含C头文件时,SWIG生成了一个公共静态void setLogFile(SWIGTYPE_p_FILE fd)函数。有什么想法吗 C功能: void setLogFile(FILE *fd); 我尝试使用下面的#1,得到以下异常: 测试一: %module Example %{ #include "headerLogFile.h" %} %i
void setLogFile(FILE *fd);
我尝试使用下面的#1,得到以下异常:
测试一:
%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
给定的test.h如下所示:
#include <stdio.h>
inline void setLogFile(FILE *fd) {
fprintf(fd, "Test\n");
fflush(fd);
}
这使用%inline
指示SWIG在定义此函数的同时包装此函数。如果您仍然使用%include“test.h”
,那么您可能会想这样做
方法2-多包一些stdio.h: 包装不仅仅是
setLogFile
,还应适当包装fopen
、fmemopen
等内容。(我个人不太喜欢这个解决方案,所以我没有举个例子)
方法3-公开一个Java接口,该接口采用:
%模块方法3
%{
#包括“test.h”
#包括
%}
// 3:
%类型映射(jni)文件*fd“jobject”
// 1:
%typemap(jstype)文件*fd“java.io.FileOutputStream”
// 2:
%typemap(jtype)文件*fd“java.io.FileDescriptor”
// 4:
%类型映射(in)(文件*fd){
jfieldID字段\u fd;
jclass_fdesc;
int-rawfd;
class_fdesc=jenv->FindClass(“java/io/FileDescriptor”);
断言(class_fdesc);
field_fd=jenv->GetFieldID(class_fdesc,“fd”,“I”);
断言(字段_fd);
rawfd=jenv->GetIntField($input,field\u fd);
$1=fdopen(rawfd,“w”);
//添加一些代码以在$1为NULL时引发Java异常(即错误)
}
// 5:
%类型映射(javain,pre=“retainFD=$javainput;”,
抛出=“java.io.IOException”)文件*fd“$javainput.getFD()
// 6:
%pragma(java)模块代码=%{
私有静态java.io.FileOutputStream retainFD;
%}
%包括“test.h”
这将实现以下功能:
java.io.FileOutputStream
Java.io.FileDescriptor
fdopen()
,以获得用于“真正”调用的文件*
FileOutputStream
并对其调用getFD()
,以获取其FileDescriptor
对象。它还添加了一个异常规范来匹配getFD()
,并执行下一点中的另一个函数文件输出流
,这将关闭文件句柄并使我们的文件*
无效。我们通过保持对FileOutputStream
的引用来实现这一点,我们是在私有静态变量中给出的。上一个类型映射的pre=“…
”会导致保留最近的一个,直到我们更改为另一个类型映射。(如果我们调用setLogFile
两次,那么释放对上一个FileOutputStream
的引用就可以了,事实上这很好。)
我先尝试了#1,但它似乎仍然找到了其他setLogFile函数,尽管我试图隐藏它。我用确切的SWIG文件和异常更新了问题,如果有帮助的话……我已经能够使用%ignore@c12-问题是,你在C中做了一些事情,这将是C++中的一个重载,但是Coesn不允许重载。您可能希望为
%inline
版本的%setLogFile
提供一个不同的名称,然后对其使用%rename
,或者只需在Java端添加一些代码,将其转发到现在调用的%inline
版本。
%module method1
%{
#include "test.h"
%}
%inline %{
void setLogFile(const char *fn) {
FILE *f = fopen(fn, "w");
setLogFile(f);
}
%}
%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"