程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了C std :: string作为带有SWIG的Java中的输出参数大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决C std :: string作为带有SWIG的Java中的输出参数?

开发过程中遇到C std :: string作为带有SWIG的Java中的输出参数的问题如何解决?下面主要结合日常开发的经验,给出你关于C std :: string作为带有SWIG的Java中的输出参数的解决方法建议,希望对你解决C std :: string作为带有SWIG的Java中的输出参数有所启发或帮助;

假设您希望在不修改现有头文件的情况下包装它,就想到了两种方法。给定我用于测试的头文件:

#include <string>

inline bool method2(const std::string & name, const std::string & alias, std::string & resurnValue, std::string & returnType) {
  resurnValue = name;
  returnType = alias;
  return true;
}

包装它的最简单方法是使用%inline创建一个将所有输出包装为一种类型的重载:

%module test

%include <std_string.i>

%{
#include "test.h"
%}

%inline %{
  struct Method2Result {
    bool b;
    std::string s1;
    std::string s2;
  };

  Method2Result method2(const std::string& in1, const std::string& in2) {
    Method2Result ret;
    ret.b = method2(in1,in2,ret.s1,ret.s2);
    return ret;
  }
%}

// Optional: don't wrap the original form of method2 at all:
%ignore method2;

%include "test.h"

这适用于:

public class run {
  public static voID main(String[] args) {
    System.loadlibrary("test");
    Method2Result ret = test.method2("foo", "bar");
    System.out.println(ret.getB() + " - " + ret.getS1() + ", " + ret.getS2());
  }
}

我怀疑您可能曾经使用过std::pairboost::tuple使用过,%template但是包装boost::tuple是不平凡的,因此您可以为成员命名一个适当的名称,库的用户将理解这些适当的名称,而不是justfirstsecond,而不必使用%rename它而变得比仅在其中编写自定义结构更冗长%inline

另外,SWIG提供了可用于%apply创建输出argumnet的OUTPUT类型映射。它们被包装为1个元素的数组- 传递数组的语义与输出参数的语义匹配。不幸的是std::string,typemaps.i中没有适合的代码,因此我们必须编写自己的代码。理想情况下,我将重用该OUTPUT_TYPEMAP文件中的宏,并稍稍修改了argout类型映射,但是它#undef无法实现。幸运的是,在这种情况下,只需复制和修改是相当简单的:

%module test

%{
#include "test.h"
%}

%typemap(Jstype) std::string& OUTPUT "String[]"
%typemap(jtype) std::string& OUTPUT "String[]"
%typemap(jni) std::string& OUTPUT "jobjectArray"
%typemap(javain)  std::string& OUTPUT "$javainput"
%typemap(in) std::string& OUTPUT (std::string temp) {
  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");
  }
  $1 = &temp;
}
%typemap(argout) std::string& OUTPUT {
  Jstring jvalue = JCALL1(NewStringUTF, jenv, temp$argnum.c_str()); 
  JCALL3(SetobjectArrayElement, jenv, $input, 0, jvalue);
}

%apply  std::string& OUTPUT { std::string & resurnValue }
%apply  std::string& OUTPUT { std::string & returnType }

%include "test.h"

可以像这样使用:

public class run {
  public static voID main(String[] args) {
    String[] out1 = new String[1];
    String[] out2 = new String[1];
    boolean retb = test.method2("foo", "bar", out1, out2);
    System.out.println(retb + " - " + out1[0] + ", " + out2[0]);
  }
}

这两个都经过测试并在我的系统上工作。对于这种情况,我喜欢这种%inline方法。(如果是成员函数,则%extend改为使用)。在一般情况下,可以使用OUTPUT类型映射,而无需编写任何额外的代码。

解决方法

我需要用SWIG包装一个C ++库,以便将其与Java一起使用。

我已经有一些方法可以使用,但是遇到一种我不知道如何解决的情况。

我有几种这样的方法:

void method1(std::string & name,std::string & result);

bool method2(std::string & name,std::string & alias,std::string & resurnValue,std::string & returnType);

注意:实际上,这是名为MyClass的类的成员方法。

我可以将第一个方法更改为返回a std::string而不是being
void,它应该可以工作;但是我不知道如何处理第二种方法,其中最后两个参数是输出参数。我已经看到了几个有关char *输出参数的问题(使用Swig/ Python在C中传递多个参数并分配字符串),但是在我的情况下应该是a
std::string,SWIG文档中没有提到这种情况,请在此处输入链接描述。此外,我可能还会遇到更多返回3个或更多输出参数的方法,这些方法可能具有不同的类型。

最终,我对接口有了一些控制,我还在开发一个类,该类充当库的入口点,但是它只是将调用传递给了实际的实现。

例如,通过这个我设法改变的方法一样method3(std::string & s)method3(const std::string &s),所以我可以从Java与正常使用String

因此,可以对方法签名进行一些修改,但是如果本机方法返回n个输出参数,则我应该将所有参数都返回(我无法创建新方法来返回每个参数)。

更新: 我一直在研究Flexo给出的解决方案,并且效果很好,但是我正在考虑做一个包装std ::
string的类,并使用该类与返回的字符串进行交互,这与Flexo的第二种解决方案非常相似,但是使用此StringWrapper而不是使用Java
String数组,基本上看起来像这样:

/*
* The MyClass.i file
*/
%module example

%include "std_string.i"

%{
    class StringPtr{

    private:
        stdString str;

    public:
        StringPtr(){

    }

        StringPtr(const stdString & str){
        this->str = stdString(str);
        }

    stdString & getStrRef(){
        return (this->str);
        }

        stdString getStrVal(){
        return stdString(this->str);
        }

        ~StringPtr(){

        }
    };


%}

/////////////////// Export StringPtr to Java

class StringPtr{

    public:
        StringPtr();

    StringPtr(const stdString & str);

    stdString getStrVal();

    ~StringPtr();

};

// I think this is nor necessary
%rename ("$ignore",fullname=1) "StringPtr::getStrRef";

%extend MyClass {

    void method1(cons std::string & name,StringPtr & result){
        $self->method1(name,result.getStrRef());
    }

    bool method2(cons std::string & name,cons std::string & alias,StringPtr & returnValue,StringPtr & returnType){
        $self->method2(name,alias,returnValue.getStrRef(),returnType.getStrRef());
    }

};

%rename ("$ignore",fullname=1) "MyClass::method1";
%rename ("$ignore",fullname=1) "MyClass::method2";

%include "MyClass.h"

因此,我想知道,从性能的角度来看,女巫更好,结构解决方案(由Flexo提供),由Flexo组成的字符串数组或该指针(就像只有一个成员的结构一样)。

大佬总结

以上是大佬教程为你收集整理的C std :: string作为带有SWIG的Java中的输出参数全部内容,希望文章能够帮你解决C std :: string作为带有SWIG的Java中的输出参数所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: