www.91084.com

GVKun编程网logo

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

8

这篇文章主要围绕SWIG:如何包装std::string&和std::string通过引用传递展开,旨在为您提供一份详细的参考资料。我们将全面介绍SWIG:如何包装std::string&的优缺点,解

这篇文章主要围绕SWIG:如何包装std :: string&std :: string通过引用传递展开,旨在为您提供一份详细的参考资料。我们将全面介绍SWIG:如何包装std :: string&的优缺点,解答std :: string通过引用传递的相关问题,同时也会为您带来.net – 如何将System :: String ^转换为std :: string?、c – sprintf如何与CString和std :: string一起使用、c – std ::在std :: string和std :: vector之间移动、c – `std :: string :: begin()`/`std :: string :: end()`的迭代器失效?的实用方法。

本文目录一览:

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

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

我正在使用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++ methodvoid foo( int & i )               -> public void foo( int[] i );    // OKvoid bar( const std::string & s ) -> public void bar( String s );   // OKvoid baz( std::string & s )       -> public void baz( SWIGTYPE_p_std__string s ); // :(

期望的:

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

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

答案1

小编典典

我能找到的最佳方法是编写自己的类型图。我一直希望有一些琐碎的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。

.net – 如何将System :: String ^转换为std :: string?

.net – 如何将System :: String ^转换为std :: string?

所以我在clr中工作,在visual c中创建.net dll.

我这样的代码:

static bool InitFile(System::String^ fileName,System::String^ container)
{
    return enc.InitFile(std::string(fileName),std::string(container));
}

有编码器,normaly resives std :: string.但是如果我从std :: string和C2440中删除通常相同的参数,那么编译器(visual studio)会给出C2664错误. VS告诉我它无法将System :: String ^转换为std :: string.

所以我很伤心……我该怎么做才能将System :: String ^变成std :: string?

更新:

现在有了你的帮助,我有了这样的代码

#include <msclr\marshal.h>
#include <stdlib.h>
#include <string.h>
using namespace msclr::interop;
namespace NsstW
{
  public ref class CFEW
  {
 public:
     CFEW() {}

     static System::String^ echo(System::String^ stringToReturn)
    {
        return stringToReturn;  
    }

     static bool InitFile(System::String^ fileName,System::String^ container)
    {   
        std::string sys_fileName = marshal_as<std::string>(fileName);;
        std::string sys_container = marshal_as<std::string>(container);;
        return enc.InitFile(sys_fileName,sys_container);
    }
...

但是当我尝试编译时,它给了我C4996

错误C4996:’msclr :: interop :: error_reporting_helper< _To_Type,_From_Type> :: marshal_as’:库不支持此转换,或者不包括此转换所需的头文件.有关添加自己的编组方法的信息,请参阅“如何:扩展封送库”的文档.

该怎么办?

解决方法

如果您使用的是VS2008或更新版本,则可以使用 automatic marshaling added to C++非常简单地执行此操作.例如,您可以通过 marshal_as将System :: String ^转换为std :: string:
System::String^ clrstring = "CLR string";
std::string stdString = marshal_as<std::string>(clrstring);

这与用于P / Invoke调用的编组相同.

c – sprintf如何与CString和std :: string一起使用

c – sprintf如何与CString和std :: string一起使用

CString s = "test";
std::string ss = "test";

char z[100];
sprintf(z,"%s",ss.c_str()); // z = "test"  : OK

char z2[100];
sprintf(z2,ss); // z2 = "(null)" : OK. undefined behavior is expected

char z3[100];
sprintf(z3,s); // z3 = "test" : How is this possible ?!

任何人都可以解释CString如何与sprintf正常工作?

解决方法

它的工作原理是因为CString类的第一个元素是一个指向char数组的指针.实际上,CString中唯一的字段是指向字符串数组的指针.这个类使用一些技巧来隐藏内部数据(如字符串长度,保留缓冲区大小等),方法是分配一个大缓冲区,然后将唯一的类指针指向char数组,以获取那些内部数据字段,它通过已知的方式移动此指针偏移.

你应该做的是调用s.GetBuffer(0);或(LPCTSTR)s;但用它作为

sprintf(z2,ss);

被MFC创建者设计允许,当然它可以在Windows下在其他平台上运行,它可能会崩溃.

[评论后编辑]

你的代码将更安全,如果不是像(LPCTSTR)那样的c风格的演员表,你将使用c cast:static_cast< LPCTSTR>(s);.但是很快你就会发现你的代码在所有这些static_cast-s中都很难看,特别是如果你的sprintf-s有很多参数的话.这是我记忆(在我看来)的设计,c风格的演员表旨在让你重新考虑你的设计,根本不使用演员表.在你的情况下,你应该使用std :: wstringstream而不是使用sprintf(假设你使用UNICODE构建):

#include<sstream>

std::wostream & operator<< (std::wostream &out,CString const &s) {
  out << s.GetString();
  return out;
}

int main(){
  CString s = _T("test");
  std::wstringstream ss;
  ss << s;  // no cast required,no UB here
  std::wcout << ss.str();
  return 0;
}

c – std ::在std :: string和std :: vector之间移动

c – std ::在std :: string和std :: vector之间移动

我正在和2个图书馆合作.一个接收并返回std :: strings,而另一个使用std :: vector< unsigned char> s.

如果我可以从std :: string和std :: vector< unsigned char>中窃取底层数组,那将是很好的并且能够将它们彼此移动而不会过度复制.

ATM我使用的东西:

const unsigned char* raw_memory =
    reinterpret_cast<const unsigned char*>(string_value.c_str()),std::vector<unsigned char>(raw_memory,raw_memory + string_value.size();

另一方面:

std::string(
    reinterpret_cast<const char*>(&vector_value[0]),vector_value.size());

能够定义一个:

std::string move_into(std::vector<unsigned char>&&);
std::vector<unsigned char> move_into(std::string&&);

解决方法

这不可能.

矢量和字符串类别不提供方式来分别从矢量或字符串中除外.他们不是要交换内容.

问题的问题是矢量和字符串可能有广泛不同的底层表示.通常在gcc中,字符串使用旧的COW(复制写入)“优化”,这与典型的向量表示(通常只是三分之一的指针/ size_t属性)有很大不同.

如果您正在处理原始字节,则将库决定将其放入字符串,并重新构建它,如果可以的话.

否则:复制. reinterpret_cast不应该是必需的,因为char和unsigned char在它们之间有隐式转换(现在,char通常默认为unsigned).

c – `std :: string :: begin()`/`std :: string :: end()`的迭代器失效?

c – `std :: string :: begin()`/`std :: string :: end()`的迭代器失效?

#include <string>
#include <iostream>

int main() {
    std::string s = "abcdef";

    std::string s2 = s;

    auto begin = const_cast<std::string const &>(s2).begin();
    auto end = s2.end();

    std::cout << end - begin << '\n';
}

此代码将begin()const的结果与end()的结果混合在一起.这些函数都不允许使任何迭代器无效.但是我很好奇是否要求end()不使iterator变量begin失效实际上意味着变量begin可以用于end.

考虑一下C8,std :: string的copy-on-write实现;非const begin()和end()函数会导致复制内部缓冲区,因为这些函数的结果可用于修改字符串.因此,上面的开始对s和s2都有效,但是使用非const end()成员会使它不再对s2(生成它的容器)有效.

上面的代码使用copy-on-write实现(例如libstdc)产生“意外”结果.而不是结束 – 开始与s2.size(),libstdc produces another number相同.

>导致开始不再是s2的有效迭代器,从中检索它的容器,构成’使迭代器无效’吗?如果你看一下迭代器的要求,它们在调用.end()之后似乎都保留了这个迭代器,所以也许begin仍然有资格作为一个有效的迭代器,因此没有被无效?
>上面的代码是否在C 98中定义得很好?在C 11中,禁止写入时复制实现?

根据我自己对规范的简要介绍,它看起来不明确,因此可能无法保证begin()和end()的结果可以一起使用,即使没有混合const和非const版本.

解决方法

如你所说,C 11在这方面与早期版本不同. C 11中没有问题,因为删除了所有允许写入时复制的尝试.在C 11之前,您的代码会导致未定义的行为;允许调用s2.end()使现有的迭代器无效(并且在g中完成,也可能仍然如此).

请注意,即使s2不是副本,标准也会允许它使迭代器无效.实际上,C 98的CD甚至可以使用f(s.begin(),s.end())或s [i] == s [j]这些未定义的行为.这只是在最后一刻才实现,并进行了更正,以便只有第一次调用begin(),end()或[]才能使迭代器无效.

我们今天的关于SWIG:如何包装std :: string&std :: string通过引用传递的分享已经告一段落,感谢您的关注,如果您想了解更多关于.net – 如何将System :: String ^转换为std :: string?、c – sprintf如何与CString和std :: string一起使用、c – std ::在std :: string和std :: vector之间移动、c – `std :: string :: begin()`/`std :: string :: end()`的迭代器失效?的相关信息,请在本站查询。

本文标签: