Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中的Swig控制器异常-在C++; 我们使用Pithon、java和C++语言使用SWIG 3.0.3../P>创建C++库的接口。 我们还提供了C++中的流接口,使用SWIG指向器特性,允许用户以所选择的支持语言中的任何一种来实现该接口。 问题是当用户的C流实现中抛出异常时,C语言的实际错误消息丢失,C++无法检索。_C#_Swig - Fatal编程技术网

C#中的Swig控制器异常-在C++; 我们使用Pithon、java和C++语言使用SWIG 3.0.3../P>创建C++库的接口。 我们还提供了C++中的流接口,使用SWIG指向器特性,允许用户以所选择的支持语言中的任何一种来实现该接口。 问题是当用户的C流实现中抛出异常时,C语言的实际错误消息丢失,C++无法检索。

C#中的Swig控制器异常-在C++; 我们使用Pithon、java和C++语言使用SWIG 3.0.3../P>创建C++库的接口。 我们还提供了C++中的流接口,使用SWIG指向器特性,允许用户以所选择的支持语言中的任何一种来实现该接口。 问题是当用户的C流实现中抛出异常时,C语言的实际错误消息丢失,C++无法检索。,c#,swig,C#,Swig,我想知道这个问题是否有解决办法 其他信息: 1。SwigJava的文档说,这个特性(在控制器中传递异常数据)是Swig3的新特性。 2。我不得不稍微修改swigpython代码以达到预期的结果 // C++ Stream Interface class Stream { virtual uint Seek(long offset, int origin); // ... }; // C# Implementation of a Stream class CustomStre

我想知道这个问题是否有解决办法

其他信息:
1。SwigJava的文档说,这个特性(在控制器中传递异常数据)是Swig3的新特性。
2。我不得不稍微修改swigpython代码以达到预期的结果

// C++ Stream Interface
class Stream 
{
    virtual uint Seek(long offset, int origin);
    // ...
};


// C# Implementation of a Stream
class CustomStream : Stream 
{
    public override uint Seek(long offset, int origin)
    {
        throw new Exception("This message should be seen in C++ caller");
        return 0;
    }
}


// C++ calling code
try 
{
    pStream->Seek(0, 0);
}
catch(std::exception e)
{
    // Here's where I want to see the exception text.
    std::cout << e.what();
}
<代码> //C++流接口 类流 { 虚拟uint寻道(长偏移、整数原点); // ... }; //C#流的实现 类CustomStream:Stream { 公共覆盖uint Seek(长偏移,整数原点) { 抛出新的异常(“此消息应在C++调用方中看到”); 返回0; } } //C++调用代码 尝试 { pStream->Seek(0,0); } 捕获(标准::异常e) { //这里是我想看到异常文本的地方。
std::cout事实证明,使用C#和SWIG真的很难做到这一点。我能提供的最好的解决方法是粗略的解决方法

为了证明这一点,我为我们制作了以下标题:

#include <iostream>

class Foo {
public:
  virtual ~Foo() {}

  virtual void Bar() = 0;
};

inline void test_catch(Foo& f) {
  try {
    f.Bar();
  }
  catch (const std::exception& e) {
    std::cerr << "Caught: " << e.what() << "\n";
  }
}
如果您将Python与SWIG结合在一起,您将使用
%特性(“director:except”)
,如中所示。不过,C#SWIG语言模块似乎不支持这一点

我们需要采用的解决策略是捕获托管异常,然后将其作为继承自
std::exception
的内容重新抛出。要将其用于C,我们需要解决两个问题:

  • 我们如何从托管代码捕获异常
  • 我们如何将代码注入到SWIG生成的输出的正确位中
  • 捕获托管代码中的异常: 看起来有两种方法可以做到这一点

    首先,如果你没有在Linux上使用mono,我想你可以捕捉到这一点,但可能不会

    第二种方法是捕获托管代码中的异常。这是可以解决的,但有点像黑客。我们可以使用csdirectorout类型映射插入代码来实现这一点:

    %typemap(csdirectorout) void %{
      try {
        $cscall;
      }
      catch(System.Exception e) {
        // pass e.ToString() somewhere now
      }
    %}
    

    这里的Bug是我们必须指定导演方法的类型——上面的例子只适用于不返回任何东西的C++函数。你可以明显地写出更多的这些类型映射(SWigType是个好的),但是在这方面有很多重复。 注入代码以作为C++本地异常重新抛出

    这甚至变得更丑陋。我没有找到任何可靠的方法将代码注入到生成的导演调用的C++侧。我希望DeReTouOutt作为返回类型与CSDistRooType类型映射一起工作,但是Sigg 3.0.2我不能让它发生(并且在运行SHIG时用‘调试-tMSEX’确认它)。。似乎没有任何地方可以使用预处理器玩把戏,调用一个给我们添加代码的宏

    我尝试的是让我的代码> CSReDistOuts<代码>再次调用C++函数,在调用C实现之前,它再次执行了。

    %模块(directors=“1”)测试
    %{
    #包括“test.hh”
    %}
    %包括
    %{
    #包括
    结构包装的异常:std::exception{
    包装的_异常(const std::string&msg):msg(msg){}
    私人:
    虚拟常量char*what()常量noexcept{
    返回msg.c_str();
    }
    std::字符串msg;
    };
    %}
    %内联%{
    void throw_native(const std::string和msg){
    抛出异常(msg);
    }
    %}
    %类型映射(csdirectorout)无效%{
    试一试{
    $cscall;
    }
    捕获(System.e例外){
    test.throw_native(例如ToString());
    }
    %}
    %特写("导演")傅,;
    %包括“test.hh”
    
    我用以下方法进行了测试:

    公共类运行库{
    静态void Main()
    {
    System.Console.WriteLine(“运行”);
    使用(Foo myFoo=new csharp派生())
    {
    测试。测试捕获物(myFoo);
    }
    }
    }
    
    <> P>当我们捕获C++中的异常时,我们将字符串传递给另一个C++函数,并在我们把它作为一个C++异常抛出的点结束,它的堆栈如下:

    ---------------------------
    抛掷(+)+ C++
    |SwigDirectorBar()| C#|
    Fo::B.(?)C++
    Test-Cad()+ C++
    |Main()| C#|
    |预主()|
    ---------------------------
    

    但当异常抛出时,运行库会爆炸——它被我使用的单点实现和阻止作为C++异常进一步传播。

    所以我现在最好的解决办法是:让C++代码设置一个全局变量,并在C++中手动检查它,在那里你可能会发现它已经被设置,即在SWIG接口:

    %inline %{
    char *exception_pending
    %} 
    %typemap(csdirectorout) void %{
      try {
        $cscall;
      }
      catch(System.Exception e) {
        test.exception_pending = e.ToString();
      }
    %}
    
    以及对
    test\u catch()
    的侵入性更改:


    作为一种解决方案,我确实不喜欢它,但它似乎是目前提供的最好的解决方案,至少在不破坏单声道兼容性和稍微修补SWIG的情况下。

    如果您展示一些代码的结构,这会很有帮助。例如,显示一个示例用户流中引发异常的C部分,并显示相应的代码G+ C++“接口”类代码。显示希望在何处使用异常消息,但实际为空。除了我的解决方法外,您还可以手动编写一个实现本机接口的托管类,然后使用以下内容将其代理到纯托管抽象类:。您需要在代理点映射异常,并且基本上SWIG对itThanks@Flexo没有帮助。这些都是好主意。吸收了所有这些…我没想到你会接受我的答案,因为我的答案是正确的
    inline void test_catch(Foo& f) {
      try {
        f.Bar();
        check_for_csharp_exception_and_raise();
      }
      catch (const std::exception& e) {
        std::cerr << "Caught: " << e.what() << "\n";
      }
    }
    
    void check_for_csharp_excception_and_raise() {
        if (exception_pending) {
            std::string msg = exception_pending;
            delete[] exception_pending;
            exception_pending = NULL;
            throw wrapped_exception(msg);
        }  
    }