在Java中处理FILE*C输入参数的SWIG配置

在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

如何配置SWIG.i文件来处理C文件*类型?下面的函数设置一个文件,以便可以将日志输出写入其中。我需要从Java类调用if。目前,当我只使用下面的函数包含C头文件时,SWIG生成了一个公共静态void setLogFile(SWIGTYPE_p_FILE fd)函数。有什么想法吗

C功能:

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
  • 然而,JNI代码的Java端将采用
    Java.io.FileDescriptor
  • JLI代码的C++侧将看到这是一个<代码>项目< /COD> < /LI>
  • 在C++方面,我们将做一些有点邪恶的事情——在代码>文件FieldReals> < /C>类()中读取私有代码>代码> int >代码>字段。这可能是不可移植的,读取类的私有部分通常被认为是不好的,但它允许我们获得一些东西,我们可以传递到
    fdopen()
    ,以获得用于“真正”调用的
    文件*
  • 大多数情况下,此类型映射采用
    FileOutputStream
    并对其调用
    getFD()
    ,以获取其
    FileDescriptor
    对象。它还添加了一个异常规范来匹配
    getFD()
    ,并执行下一点中的另一个函数
  • 我们需要确保Java不会垃圾收集并完成
    文件输出流
    ,这将关闭文件句柄并使我们的
    文件*
    无效。我们通过保持对
    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"