这篇文章主要围绕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包)
- .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从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?
我这样的代码:
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’:库不支持此转换,或者不包括此转换所需的头文件.有关添加自己的编组方法的信息,请参阅“如何:扩展封送库”的文档.
该怎么办?
解决方法
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一起使用
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正常工作?
解决方法
你应该做的是调用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之间移动
如果我可以从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()`的迭代器失效?
#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版本.
解决方法
请注意,即使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()`的迭代器失效?的相关信息,请在本站查询。
本文标签: