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,我们需要解决两个问题:
%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);
}
}