SWIG 3 中文手册——12. 自定义功能

The %exception directive allows you to define a general purpose exception handler. For example, you can specify the following:

%exception 指令允许你定义通用异常处理程序。例如,你可以指定以下内容:

%exception {

  try {

    $action

  }

  catch (RangeError) {

    ... handle error ...

  }

}

How the exception is handled depends on the target language, for example, Python:

异常的处理方式取决于目标语言,例如在 Python 中:

%exception {

  try {

    $action

  }

  catch (RangeError) {

    PyErr_SetString(PyExc_IndexError, "index out-of-bounds");

    SWIG_fail;

  }

}

When defined, the code enclosed in braces is inserted directly into the low-level wrapper functions. The special variable $action is one of a few %exception special variables supported and gets replaced with the actual operation to be performed (a function call, method invocation, attribute access, etc.). An exception handler remains in effect until it is explicitly deleted. This is done by using either %exception or %noexception with no code. For example:

一旦定义,用大括号括起来的代码直接插入到低级包装器函数中。特殊变量 $action 是受支持的少数 %exception 特殊变量之一,并被替换为要执行的实际操作(函数调用、方法调用、属性访问等)。异常处理程序将一直有效,直到被明确删除。这可以通过 %exception 或 %noexception 来完成,无须编写代码。例如:

%exception;  // Deletes any previously defined handler

Compatibility note: Previous versions of SWIG used a special directive %except for exception handling. That directive is deprecated--%exception provides the same functionality, but is substantially more flexible.

注意兼容性:早期版本的 SWIG 使用特殊指令 %except 进行异常处理。该指令已被弃用——%exception 提供相同的功能,但实质上更为灵活。

12.1.1 C 代码中的异常处理

C has no formal exception handling mechanism so there are several approaches that might be used. A somewhat common technique is to simply set a special error code. For example:

C 没有正式的异常处理机制,因此可以使用几种方法来实现。某种常见的技术是简单地设置特殊的错误代码。例如:

/* File : except.c */

static char error_message[256];

static int error_status = 0;

void throw_exception(char *msg) {

  strncpy(error_message, msg, 256);

  error_status = 1;

}

void clear_exception() {

  error_status = 0;

}

char *check_exception() {

  if (error_status)

    return error_message;

  else

    return NULL;

}

To use these functions, functions simply call throw_exception() to indicate an error occurred. For example :

要使用这些函数,函数只需调用 throw_exception() 来指示发生了错误。例如 :

double inv(double x) {

  if (x != 0)

    return 1.0/x;

  else {

    throw_exception("Division by zero");

    return 0;

  }

}

To catch the exception, you can write a simple exception handler such as the following (shown for Perl5) :

要捕获异常,你可以编写一个简单的异常处理程序,例如以下代码(针对 Perl5):

%exception {

  char *err;

  clear_exception();

  $action

  if ((err = check_exception())) {

    croak(err);

  }

}

In this case, when an error occurs, it is translated into a Perl error. Each target language has its own approach to creating a runtime error/exception in and for Perl it is the croak method shown above.

在这种情况下,一旦错误发生,它将转换为 Perl 错误。每种目标语言都有自己的方法来在其中创建运行时错误/异常,对于 Perl 来说,这是上面显示的 croak 方法。

12.1.2 用 longjmp() 处理异常

Exception handling can also be added to C code using the library. Here is a minimalistic implementation that relies on the C preprocessor :

也可以使用 库将异常处理添加到 C 代码中。这是一个依赖 C 预处理器的简约实现:

/* File : except.c

  Just the declaration of a few global variables we're going to use */

#include

jmp_buf exception_buffer;

int exception_status;

/* File : except.h */

#include

extern jmp_buf exception_buffer;

extern int exception_status;

#define try if ((exception_status = setjmp(exception_buffer)) == 0)

#define catch(val) else if (exception_status == val)

#define throw(val) longjmp(exception_buffer, val)

#define finally else

/* Exception codes */

#define RangeError    1

#define DivisionByZero 2

#define OutOfMemory    3

Now, within a C program, you can do the following :

现在,在 C 程序中,你可以这样做:

double inv(double x) {

  if (x)

    return 1.0/x;

  else

    throw(DivisionByZero);

}

Finally, to create a SWIG exception handler, write the following :

最终,如下可以创建一个 SWIG 异常处理器:

%{

#include "except.h"

%}

%exception {

  try {

    $action

  } catch(RangeError) {

    croak("Range Error");

  } catch(DivisionByZero) {

    croak("Division by zero");

  } catch(OutOfMemory) {

    croak("Out of memory");

  } finally {

    croak("Unknown exception");

  }

}

Note: This implementation is only intended to illustrate the general idea. To make it work better, you'll need to modify it to handle nested try declarations.

注意:此实现仅用于说明一般想法。为了使其更好地工作,你需要对其进行修改以处理嵌套的 try 声明。

12.1.3 处理 C++ 异常

Handling C++ exceptions is also straightforward. For example:

处理 C++ 异常也很简单。例如:

%exception {

  try {

    $action

  } catch(RangeError) {

    croak("Range Error");

  } catch(DivisionByZero) {

    croak("Division by zero");

  } catch(OutOfMemory) {

    croak("Out of memory");

  } catch(...) {

    croak("Unknown exception");

  }

}

The exception types need to be declared as classes elsewhere, possibly in a header file :

异常类型需要在其他地方声明为类,可能是在头文件中:

class RangeError {};

class DivisionByZero {};

class OutOfMemory {};

12.1.4 变量的异常处理器

By default all variables will ignore %exception, so it is effectively turned off for all variables wrappers. This applies to global variables, member variables and static member variables. The approach is certainly a logical one when wrapping variables in C. However, in C++, it is quite possible for an exception to be thrown while the variable is being assigned. To ensure %exception is used when wrapping variables, it needs to be 'turned on' using the %allowexception feature. Note that %allowexception is just a macro for %feature("allowexcept"), that is, it is a feature called allowexcept. Any variable which has this feature attached to it, will then use the %exception feature, but of course, only if there is a %exception attached to the variable in the first place. The %allowexception feature works like any other feature and so can be used globally or for selective variables.

默认情况下,所有变量都将忽略 %exception,因此对于所有变量包装器均将其关闭。这适用于全局变量、成员变量和静态成员变量。在用 C 包装变量时,这种方法当然是合乎逻辑的。但是,在 C++ 中,很可能在分配变量时引发异常。为了确保在包装变量时使用 %exception,需要使用 %allowexception 功能将其 turned on。请注意,%allowexception 只是 %feature("allowexcept") 的宏,也就是说,它是一个名为allowexcept 的功能。任何具有此功能的变量都将使用 %exception 功能,但是,前提当然是首先要在变量上附加 %exception。%allowexception 功能与任何其他功能一样工作,因此可以全局使用或用于选择性变量。

%allowexception;                // turn on globally

%allowexception Klass::MyVar;  // turn on for a specific variable

%noallowexception Klass::MyVar; // turn off for a specific variable

%noallowexception;              // turn off globally

12.1.5 定义不同的异常处理器

By default, the %exception directive creates an exception handler that is used for all wrapper functions that follow it. Unless there is a well-defined (and simple) error handling mechanism in place, defining one universal exception handler may be unwieldy and result in excessive code bloat since the handler is inlined into each wrapper function.

To fix this, you can be more selective about how you use the %exception directive. One approach is to only place it around critical pieces of code. For example:

默认情况下,%exception 指令创建一个异常处理程序,该异常处理程序用于其后的所有包装函数。除非有一个定义明确(且简单)的错误处理机制,否则定义一个通用异常处理程序可能会很麻烦,并且由于该处理程序被内联到每个包装器函数中,因此会导致代码过于膨胀。

为了解决这个问题,你可以更具选择性地使用 %exception 指令。一种方法是仅将其放置在关键的代码周围。例如:

%exception {

  ... your exception handler ...

}

/* Define critical operations that can throw exceptions here */

%exception;

/* Define non-critical operations that don't throw exceptions */

More precise control over exception handling can be obtained by attaching an exception handler to specific declaration name. For example:

通过将异常处理程序附加到特定的声明名称,可以获得对异常处理更精确的控制。例如:

%exception allocate {

  try {

    $action

  }

  catch (MemoryError) {

    croak("Out of memory");

  }

}

In this case, the exception handler is only attached to declarations named allocate. This would include both global and member functions. The names supplied to %exception follow the same rules as for %rename described in the section on Ambiguity resolution and renaming. For example, if you wanted to define an exception handler for a specific class, you might write this:

在这种情况下,异常处理程序仅附加到名为 allocate 的声明。这将包括全局和成员函数。提供给 %exception 的名称遵循与消歧义和重命名一节中所述的 %rename 相同的规则。例如,如果你想为特定的类定义异常处理程序,则可以这样编写:

%exception Object::allocate {

  try {

    $action

  }

  catch (MemoryError) {

    croak("Out of memory");

  }

}

When a class prefix is supplied, the exception handler is applied to the corresponding declaration in the specified class as well as for identically named functions appearing in derived classes.

%exception can even be used to pinpoint a precise declaration when overloading is used. For example:

提供类前缀时,异常处理程序将应用于指定类中的相应声明,以及派生类中出现的名称相同的函数。

使用重载时,甚至可以使用 %exception 来精确定位声明。例如:

%exception Object::allocate(int) {

  try {

    $action

  }

  catch (MemoryError) {

    croak("Out of memory");

  }

}

Attaching exceptions to specific declarations is a good way to reduce code bloat. It can also be a useful way to attach exceptions to specific parts of a header file. For example:

将异常附加到特定声明是减少代码膨胀的好方法。将异常附加到头文件的特定部分也是一种有用的方法。例如:

%module example

%{

#include "someheader.h"

%}

// Define a few exception handlers for specific declarations

%exception Object::allocate(int) {

  try {

    $action

  }

  catch (MemoryError) {

    croak("Out of memory");

  }

}

%exception Object::getitem {

  try {

    $action

  }

  catch (RangeError) {

    croak("Index out of range");

  }

}

...

// Read a raw header file

%include "someheader.h"

Compatibility note: The %exception directive replaces the functionality provided by the deprecated except typemap. The typemap would allow exceptions to be thrown in the target language based on the return type of a function and was intended to be a mechanism for pinpointing specific declarations. However, it never really worked that well and the new %exception directive is much better.

注意兼容性:%exception 指令替换了不推荐使用的 except 类型映射提供的功能。类型映射将允许根据函数的返回类型以目标语言抛出异常,并且该映射旨在成为一种精确定位特定声明的机制。但是,它从来没有真正奏效过,新的 %exception 指令要好得多。

12.1.6 %exception 的特殊变量

The %exception directive supports a few special variables which are placeholders for code substitution. The following table shows the available special variables and details what the special variables are replaced with.

%exception 指令支持一些特殊变量,它们是代码替换的占位符。下表显示了可用的特殊变量,并详细说明了用哪些特殊变量替换的变量。

$action The actual operation to be performed (a function call, method invocation, variable access, etc.)

$name The C/C++ symbol name for the function.

$symname The symbol name used internally by SWIG

$overname The extra mangling used in the symbol name for overloaded method. Expands to nothing if the wrapped method is not overloaded.

$wrapname The language specific wrapper name (usually a C function name exported from the shared object/dll)

$decl The fully qualified C/C++ declaration of the method being wrapped without the return type

$fulldecl The fully qualified C/C++ declaration of the method being wrapped including the return type

$parentclassname The parent class name (if any) for a method.

$parentclasssymname The target language parent class name (if any) for a method.

The special variables are often used in situations where method calls are logged. Exactly which form of the method call needs logging is up to individual requirements, but the example code below shows all the possible expansions, plus how an exception message could be tailored to show the C++ method declaration:

特殊变量通常用于记录方法调用的情况。究竟哪种形式的方法调用需要记录取决于个人要求,但是下面的示例代码显示了所有可能的扩展,以及如何定制异常消息以显示 C++ 方法声明:

%exception Special::something {

  log("symname: $symname");

  log("overname: $overname");

  log("wrapname: $wrapname");

  log("decl: $decl");

  log("fulldecl: $fulldecl");

  try {

    $action

  }

  catch (MemoryError) {

      croak("Out of memory in $decl");

  }

}

void log(const char *message);

struct Special {

  void something(const char *c);

  void something(int i);

};

Below shows the expansions for the 1st of the overloaded something wrapper methods for Perl:

下面显示了 Perl 重载的 something 包装器方法的第一种扩展:

log("symname: Special_something");

log("overname: __SWIG_0");

log("wrapname: _wrap_Special_something__SWIG_0");

log("decl: Special::something(char const *)");

log("fulldecl: void Special::something(char const *)");

try {

  (arg1)->something((char const *)arg2);

}

catch (MemoryError) {

  croak("Out of memory in Special::something(char const *)");

}

12.1.7 使用 SWIG 异常库

The exception.i library file provides support for creating language independent exceptions in your interfaces. To use it, simply put an "%include exception.i" in your interface file. This provides a function SWIG_exception() that can be used to raise common scripting language exceptions in a portable manner. For example :

exception.i 库文件支持在接口文件中创建独立于语言的异常。要使用它,只需在接口文件中引入 %include exception.i。这提供了一个函数 SWIG_exception(),该函数可用于以可移植的方式引发常见的脚本语言异常。例如 :

// Language independent exception handler

%include exception.i

%exception {

  try {

    $action

  } catch(RangeError) {

    SWIG_exception(SWIG_ValueError, "Range Error");

  } catch(DivisionByZero) {

    SWIG_exception(SWIG_DivisionByZero, "Division by zero");

  } catch(OutOfMemory) {

    SWIG_exception(SWIG_MemoryError, "Out of memory");

  } catch(...) {

    SWIG_exception(SWIG_RuntimeError, "Unknown exception");

  }

}

As arguments, SWIG_exception() takes an error type code (an integer) and an error message string. The currently supported error types are :

作为参数,SWIG_exception() 采用错误类型代码(整数)和错误消息字符串。当前支持的错误类型是:

SWIG_UnknownError

SWIG_IOError

SWIG_RuntimeError

SWIG_IndexError

SWIG_TypeError

SWIG_DivisionByZero

SWIG_OverflowError

SWIG_SyntaxError

SWIG_ValueError

SWIG_SystemError

SWIG_AttributeError

SWIG_MemoryError

SWIG_NullReferenceError

The %exception directive allows you to define a general purpose exception handler. For example, you can specify the following:

%exception 指令允许你定义通用异常处理程序。例如,你可以指定以下内容:

%exception {

  try {

    $action

  }

  catch (RangeError) {

    ... handle error ...

  }

}

How the exception is handled depends on the target language, for example, Python:

异常的处理方式取决于目标语言,例如在 Python 中:

%exception {

  try {

    $action

  }

  catch (RangeError) {

    PyErr_SetString(PyExc_IndexError, "index out-of-bounds");

    SWIG_fail;

  }

}

When defined, the code enclosed in braces is inserted directly into the low-level wrapper functions. The special variable $action is one of a few %exception special variables supported and gets replaced with the actual operation to be performed (a function call, method invocation, attribute access, etc.). An exception handler remains in effect until it is explicitly deleted. This is done by using either %exception or %noexception with no code. For example:

一旦定义,用大括号括起来的代码直接插入到低级包装器函数中。特殊变量 $action 是受支持的少数 %exception 特殊变量之一,并被替换为要执行的实际操作(函数调用、方法调用、属性访问等)。异常处理程序将一直有效,直到被明确删除。这可以通过 %exception 或 %noexception 来完成,无须编写代码。例如:

%exception;  // Deletes any previously defined handler

Compatibility note: Previous versions of SWIG used a special directive %except for exception handling. That directive is deprecated--%exception provides the same functionality, but is substantially more flexible.

注意兼容性:早期版本的 SWIG 使用特殊指令 %except 进行异常处理。该指令已被弃用——%exception 提供相同的功能,但实质上更为灵活。

12.1.1 C 代码中的异常处理

C has no formal exception handling mechanism so there are several approaches that might be used. A somewhat common technique is to simply set a special error code. For example:

C 没有正式的异常处理机制,因此可以使用几种方法来实现。某种常见的技术是简单地设置特殊的错误代码。例如:

/* File : except.c */

static char error_message[256];

static int error_status = 0;

void throw_exception(char *msg) {

  strncpy(error_message, msg, 256);

  error_status = 1;

}

void clear_exception() {

  error_status = 0;

}

char *check_exception() {

  if (error_status)

    return error_message;

  else

    return NULL;

}

To use these functions, functions simply call throw_exception() to indicate an error occurred. For example :

要使用这些函数,函数只需调用 throw_exception() 来指示发生了错误。例如 :

double inv(double x) {

  if (x != 0)

    return 1.0/x;

  else {

    throw_exception("Division by zero");

    return 0;

  }

}

To catch the exception, you can write a simple exception handler such as the following (shown for Perl5) :

要捕获异常,你可以编写一个简单的异常处理程序,例如以下代码(针对 Perl5):

%exception {

  char *err;

  clear_exception();

  $action

  if ((err = check_exception())) {

    croak(err);

  }

}

In this case, when an error occurs, it is translated into a Perl error. Each target language has its own approach to creating a runtime error/exception in and for Perl it is the croak method shown above.

在这种情况下,一旦错误发生,它将转换为 Perl 错误。每种目标语言都有自己的方法来在其中创建运行时错误/异常,对于 Perl 来说,这是上面显示的 croak 方法。

12.1.2 用 longjmp() 处理异常

Exception handling can also be added to C code using the library. Here is a minimalistic implementation that relies on the C preprocessor :

也可以使用 库将异常处理添加到 C 代码中。这是一个依赖 C 预处理器的简约实现:

/* File : except.c

  Just the declaration of a few global variables we're going to use */

#include

jmp_buf exception_buffer;

int exception_status;

/* File : except.h */

#include

extern jmp_buf exception_buffer;

extern int exception_status;

#define try if ((exception_status = setjmp(exception_buffer)) == 0)

#define catch(val) else if (exception_status == val)

#define throw(val) longjmp(exception_buffer, val)

#define finally else

/* Exception codes */

#define RangeError    1

#define DivisionByZero 2

#define OutOfMemory    3

Now, within a C program, you can do the following :

现在,在 C 程序中,你可以这样做:

double inv(double x) {

  if (x)

    return 1.0/x;

  else

    throw(DivisionByZero);

}

Finally, to create a SWIG exception handler, write the following :

最终,如下可以创建一个 SWIG 异常处理器:

%{

#include "except.h"

%}

%exception {

  try {

    $action

  } catch(RangeError) {

    croak("Range Error");

  } catch(DivisionByZero) {

    croak("Division by zero");

  } catch(OutOfMemory) {

    croak("Out of memory");

  } finally {

    croak("Unknown exception");

  }

}

Note: This implementation is only intended to illustrate the general idea. To make it work better, you'll need to modify it to handle nested try declarations.

注意:此实现仅用于说明一般想法。为了使其更好地工作,你需要对其进行修改以处理嵌套的 try 声明。

12.1.3 处理 C++ 异常

Handling C++ exceptions is also straightforward. For example:

处理 C++ 异常也很简单。例如:

%exception {

  try {

    $action

  } catch(RangeError) {

    croak("Range Error");

  } catch(DivisionByZero) {

    croak("Division by zero");

  } catch(OutOfMemory) {

    croak("Out of memory");

  } catch(...) {

    croak("Unknown exception");

  }

}

The exception types need to be declared as classes elsewhere, possibly in a header file :

异常类型需要在其他地方声明为类,可能是在头文件中:

class RangeError {};

class DivisionByZero {};

class OutOfMemory {};

12.1.4 变量的异常处理器

By default all variables will ignore %exception, so it is effectively turned off for all variables wrappers. This applies to global variables, member variables and static member variables. The approach is certainly a logical one when wrapping variables in C. However, in C++, it is quite possible for an exception to be thrown while the variable is being assigned. To ensure %exception is used when wrapping variables, it needs to be 'turned on' using the %allowexception feature. Note that %allowexception is just a macro for %feature("allowexcept"), that is, it is a feature called allowexcept. Any variable which has this feature attached to it, will then use the %exception feature, but of course, only if there is a %exception attached to the variable in the first place. The %allowexception feature works like any other feature and so can be used globally or for selective variables.

默认情况下,所有变量都将忽略 %exception,因此对于所有变量包装器均将其关闭。这适用于全局变量、成员变量和静态成员变量。在用 C 包装变量时,这种方法当然是合乎逻辑的。但是,在 C++ 中,很可能在分配变量时引发异常。为了确保在包装变量时使用 %exception,需要使用 %allowexception 功能将其 turned on。请注意,%allowexception 只是 %feature("allowexcept") 的宏,也就是说,它是一个名为allowexcept 的功能。任何具有此功能的变量都将使用 %exception 功能,但是,前提当然是首先要在变量上附加 %exception。%allowexception 功能与任何其他功能一样工作,因此可以全局使用或用于选择性变量。

%allowexception;                // turn on globally

%allowexception Klass::MyVar;  // turn on for a specific variable

%noallowexception Klass::MyVar; // turn off for a specific variable

%noallowexception;              // turn off globally

12.1.5 定义不同的异常处理器

By default, the %exception directive creates an exception handler that is used for all wrapper functions that follow it. Unless there is a well-defined (and simple) error handling mechanism in place, defining one universal exception handler may be unwieldy and result in excessive code bloat since the handler is inlined into each wrapper function.

To fix this, you can be more selective about how you use the %exception directive. One approach is to only place it around critical pieces of code. For example:

默认情况下,%exception 指令创建一个异常处理程序,该异常处理程序用于其后的所有包装函数。除非有一个定义明确(且简单)的错误处理机制,否则定义一个通用异常处理程序可能会很麻烦,并且由于该处理程序被内联到每个包装器函数中,因此会导致代码过于膨胀。

为了解决这个问题,你可以更具选择性地使用 %exception 指令。一种方法是仅将其放置在关键的代码周围。例如:

%exception {

  ... your exception handler ...

}

/* Define critical operations that can throw exceptions here */

%exception;

/* Define non-critical operations that don't throw exceptions */

More precise control over exception handling can be obtained by attaching an exception handler to specific declaration name. For example:

通过将异常处理程序附加到特定的声明名称,可以获得对异常处理更精确的控制。例如:

%exception allocate {

  try {

    $action

  }

  catch (MemoryError) {

    croak("Out of memory");

  }

}

In this case, the exception handler is only attached to declarations named allocate. This would include both global and member functions. The names supplied to %exception follow the same rules as for %rename described in the section on Ambiguity resolution and renaming. For example, if you wanted to define an exception handler for a specific class, you might write this:

在这种情况下,异常处理程序仅附加到名为 allocate 的声明。这将包括全局和成员函数。提供给 %exception 的名称遵循与消歧义和重命名一节中所述的 %rename 相同的规则。例如,如果你想为特定的类定义异常处理程序,则可以这样编写:

%exception Object::allocate {

  try {

    $action

  }

  catch (MemoryError) {

    croak("Out of memory");

  }

}

When a class prefix is supplied, the exception handler is applied to the corresponding declaration in the specified class as well as for identically named functions appearing in derived classes.

%exception can even be used to pinpoint a precise declaration when overloading is used. For example:

提供类前缀时,异常处理程序将应用于指定类中的相应声明,以及派生类中出现的名称相同的函数。

使用重载时,甚至可以使用 %exception 来精确定位声明。例如:

%exception Object::allocate(int) {

  try {

    $action

  }

  catch (MemoryError) {

    croak("Out of memory");

  }

}

Attaching exceptions to specific declarations is a good way to reduce code bloat. It can also be a useful way to attach exceptions to specific parts of a header file. For example:

将异常附加到特定声明是减少代码膨胀的好方法。将异常附加到头文件的特定部分也是一种有用的方法。例如:

%module example

%{

#include "someheader.h"

%}

// Define a few exception handlers for specific declarations

%exception Object::allocate(int) {

  try {

    $action

  }

  catch (MemoryError) {

    croak("Out of memory");

  }

}

%exception Object::getitem {

  try {

    $action

  }

  catch (RangeError) {

    croak("Index out of range");

  }

}

...

// Read a raw header file

%include "someheader.h"

Compatibility note: The %exception directive replaces the functionality provided by the deprecated except typemap. The typemap would allow exceptions to be thrown in the target language based on the return type of a function and was intended to be a mechanism for pinpointing specific declarations. However, it never really worked that well and the new %exception directive is much better.

注意兼容性:%exception 指令替换了不推荐使用的 except 类型映射提供的功能。类型映射将允许根据函数的返回类型以目标语言抛出异常,并且该映射旨在成为一种精确定位特定声明的机制。但是,它从来没有真正奏效过,新的 %exception 指令要好得多。

12.1.6 %exception 的特殊变量

The %exception directive supports a few special variables which are placeholders for code substitution. The following table shows the available special variables and details what the special variables are replaced with.

%exception 指令支持一些特殊变量,它们是代码替换的占位符。下表显示了可用的特殊变量,并详细说明了用哪些特殊变量替换的变量。

$action The actual operation to be performed (a function call, method invocation, variable access, etc.)

$name The C/C++ symbol name for the function.

$symname The symbol name used internally by SWIG

$overname The extra mangling used in the symbol name for overloaded method. Expands to nothing if the wrapped method is not overloaded.

$wrapname The language specific wrapper name (usually a C function name exported from the shared object/dll)

$decl The fully qualified C/C++ declaration of the method being wrapped without the return type

$fulldecl The fully qualified C/C++ declaration of the method being wrapped including the return type

$parentclassname The parent class name (if any) for a method.

$parentclasssymname The target language parent class name (if any) for a method.

The special variables are often used in situations where method calls are logged. Exactly which form of the method call needs logging is up to individual requirements, but the example code below shows all the possible expansions, plus how an exception message could be tailored to show the C++ method declaration:

特殊变量通常用于记录方法调用的情况。究竟哪种形式的方法调用需要记录取决于个人要求,但是下面的示例代码显示了所有可能的扩展,以及如何定制异常消息以显示 C++ 方法声明:

%exception Special::something {

  log("symname: $symname");

  log("overname: $overname");

  log("wrapname: $wrapname");

  log("decl: $decl");

  log("fulldecl: $fulldecl");

  try {

    $action

  }

  catch (MemoryError) {

      croak("Out of memory in $decl");

  }

}

void log(const char *message);

struct Special {

  void something(const char *c);

  void something(int i);

};

Below shows the expansions for the 1st of the overloaded something wrapper methods for Perl:

下面显示了 Perl 重载的 something 包装器方法的第一种扩展:

log("symname: Special_something");

log("overname: __SWIG_0");

log("wrapname: _wrap_Special_something__SWIG_0");

log("decl: Special::something(char const *)");

log("fulldecl: void Special::something(char const *)");

try {

  (arg1)->something((char const *)arg2);

}

catch (MemoryError) {

  croak("Out of memory in Special::something(char const *)");

}

12.1.7 使用 SWIG 异常库

The exception.i library file provides support for creating language independent exceptions in your interfaces. To use it, simply put an "%include exception.i" in your interface file. This provides a function SWIG_exception() that can be used to raise common scripting language exceptions in a portable manner. For example :

exception.i 库文件支持在接口文件中创建独立于语言的异常。要使用它,只需在接口文件中引入 %include exception.i。这提供了一个函数 SWIG_exception(),该函数可用于以可移植的方式引发常见的脚本语言异常。例如 :

// Language independent exception handler

%include exception.i

%exception {

  try {

    $action

  } catch(RangeError) {

    SWIG_exception(SWIG_ValueError, "Range Error");

  } catch(DivisionByZero) {

    SWIG_exception(SWIG_DivisionByZero, "Division by zero");

  } catch(OutOfMemory) {

    SWIG_exception(SWIG_MemoryError, "Out of memory");

  } catch(...) {

    SWIG_exception(SWIG_RuntimeError, "Unknown exception");

  }

}

As arguments, SWIG_exception() takes an error type code (an integer) and an error message string. The currently supported error types are :

作为参数,SWIG_exception() 采用错误类型代码(整数)和错误消息字符串。当前支持的错误类型是:

SWIG_UnknownError

SWIG_IOError

SWIG_RuntimeError

SWIG_IndexError

SWIG_TypeError

SWIG_DivisionByZero

SWIG_OverflowError

SWIG_SyntaxError

SWIG_ValueError

SWIG_SystemError

SWIG_AttributeError

SWIG_MemoryError

SWIG_NullReferenceErro亚马逊测评www.yisuping.com

你可能感兴趣的:(SWIG 3 中文手册——12. 自定义功能)