当前位置: 首页 > 面试题库 >

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

高承望
2023-03-14
问题内容

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

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

我有参考暴露为Java数组传递原语,感谢typemaps.i,和const std::string&s
^暴露java.lang.String,感谢std_string.i。但是非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

更新 :我找到 解决方案,如下所述。但是,它花费了超过几秒钟的时间。我仍然对听到简单的方法感兴趣。


问题答案:

我能找到的最佳方法是编写自己的类型图。我一直希望有一些琐碎的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。如果非空,则将其转换为UTF-8 std :: string值并传递给C
++函数。在退出时,通过引用传递的std :: string的值将从UTF-8转换回Java String。



 类似资料:
  • 问题内容: 我已经看到了很多类似的问题,但是还没有找到解决我特定问题的方法。我正在尝试SWIGify一些使用std :: function的C ++ 11代码,因此可以在Java应用程序中使用它。 我遇到了这样的共享指针: 并使用shared_ptr指令成功处理了它们,如下所示: 我遇到了像这样的共享指针向量: 并使用如下模板成功处理了它们: 现在我有一个这样的方法: 而且我无法让SWIG正确包装

  • 微软(修复了它) 我们已经在未来的版本中修复了这个问题。现在MSVC提供如下错误:错误C2664:'void std::basic_string,std::allocator>::push_back(const_elem)':无法用[_elem=char]将参数1从“std::byte”转换为“const_elem”

  • 问题内容: 我需要用SWIG包装一个C ++库,以便将其与Java一起使用。 我已经有一些方法可以使用,但是遇到一种我不知道如何解决的情况。 我有几种这样的方法: 注意:实际上,这是名为MyClass的类的成员方法。 我可以将第一个方法更改为返回a 而不是being ,它应该可以工作;但是我不知道如何处理第二种方法,其中最后两个参数是输出参数。我已经看到了几个有关输出参数的问题(使用Swig/ P

  • 可能重复: 是传递const std::string的天数 如果支持移动语义学,我应该通过值传递d::字符串吗?那么使用小字符串优化(SSO)的实现呢?

  • 显然,SWIG不理解并破坏Python绑定。例如,这适用于C: 但是这会破坏代码(除了为了简单起见有不同的行为,但这不是重点): (普通)未绑定函数的情况相同。那么,有人知道解决这个问题的方法吗?

  • 此示例代码是否在所有系统上导致两个相等的值?