SWIG:如何包装std :: string& (std :: string通过引用传递)

时间:2010-09-20 16:36:25

标签: java c++ swig

我正在使用SWIG从Java访问C ++代码。

公开非const引用传递的std :: string参数的最简单方法是什么?

由于stma_string.i,我将原型通过引用传递给Java数组,这要归功于typemaps.i和const std::string&公开为java.lang.String。但是非const std :: string&公开为不透明指针类型SWIGTYPE_p_std__string

电流:

// C++ method                     -> // Java wrapper of C++ method
void foo( int & i )               -> public void foo( int[] i );    // OK
void bar( const std::string & s ) -> public void bar( String s );   // OK
void baz( std::string & s )       -> public void baz( SWIGTYPE_p_std__string s ); // :(

所需:

void foo( int & i )               -> public void foo( int[] i );    // OK
void bar( const std::string & s ) -> public void bar( String s );   // OK
void baz( std::string & s )       -> public void baz( String[] s ); // OK

更新:我找到了 解决方案,如下所述。但是,它需要花费更多精力而不是几秒钟。我仍然对听到简单的方法感兴趣。

1 个答案:

答案 0 :(得分:7)

我能找到的最佳方法是编写自己的typemap。我一直希望有一些简单的SWIG指令。

如果其他人需要这个,我就是这样做的。请记住,我不是SWIG专家。

首先,您需要定义一些要应用于std :: string&的字体图。参数。您只需要定义一次。 (注意:在某些配置中可能还需要其他类型图。)

%typemap(jni) std::string *INOUT, std::string &INOUT %{jobjectArray%}
%typemap(jtype) std::string *INOUT, std::string &INOUT "java.lang.String[]"
%typemap(jstype) std::string *INOUT, std::string &INOUT "java.lang.String[]"
%typemap(javain) std::string *INOUT, std::string &INOUT "$javainput"

%typemap(in) std::string *INOUT (std::string strTemp ), std::string &INOUT (std::string strTemp ) {
  if (!$input) {
    SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
    return $null;
  }
  if (JCALL1(GetArrayLength, jenv, $input) == 0) {
    SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
    return $null;
  }

  jobject oInput = JCALL2(GetObjectArrayElement, jenv, $input, 0); 
  if ( NULL != oInput ) {
    jstring sInput = static_cast<jstring>( oInput );

    const char * $1_pstr = (const char *)jenv->GetStringUTFChars(sInput, 0); 
    if (!$1_pstr) return $null;
    strTemp.assign( $1_pstr );
    jenv->ReleaseStringUTFChars( sInput, $1_pstr);  
  }

  $1 = &strTemp;
}

%typemap(freearg) std::string *INOUT, std::string &INOUT ""

%typemap(argout) std::string *INOUT, std::string &INOUT
{ 
  jstring jStrTemp = jenv->NewStringUTF( strTemp$argnum.c_str() );
  JCALL3(SetObjectArrayElement, jenv, $input, 0, jStrTemp ); 
}

接下来,每个 C ++参数模式都是这样的......

void foo( std::string & xyzzy );
void bar( std::string & xyzzy );
void baz( ..., std::string & xyzzy, ... );

...您使用此SWIG指令应用上面的类型映射:

%apply std::string &INOUT { std::string & xyzzy };

生成的绑定如下所示:

public void foo( java.lang.String[] xyzzy );
public void bar( java.lang.String[] xyzzy );
public void baz( ..., java.lang.String[] xyzzy, ... );

它们每个都需要一个单元素的String数组。在输入时,第一个元素可以为null。如果为非null,则将其转换为UTF-8 std :: string值并传递给C ++函数。退出时,引用传递的std :: string的值将从UTF-8转换回Java String。