主頁 > 後端開發 > SWIG 3 中文手冊——12. 自定義功能

SWIG 3 中文手冊——12. 自定義功能

2020-09-11 08:45:07 後端開發

目錄

  • 12 自定義功能
    • 12.1 用 %exception 處理例外
      • 12.1.1 C 代碼中的例外處理
      • 12.1.2 用 longjmp() 處理例外
      • 12.1.3 處理 C++ 例外
      • 12.1.4 變數的例外處理器
      • 12.1.5 定義不同的例外處理器
      • 12.1.6 %exception 的特殊變數
      • 12.1.7 使用 SWIG 例外庫
    • 12.2 物件所有權與 %newobject
    • 12.3 功能與 %feature 指令
      • 12.3.1 功能屬性
      • 12.3.2 功能標志
      • 12.3.3 清除功能
      • 12.3.4 功能與默認引數
      • 12.3.5 功能示例

12 自定義功能

In many cases, it is desirable to change the default wrapping of particular declarations in an interface. For example, you might want to provide hooks for catching C++ exceptions, add assertions, or provide hints to the underlying code generator. This chapter describes some of these customization techniques. First, a discussion of exception handling is presented. Then, a more general-purpose customization mechanism known as "features" is described.

在許多情況下,用戶希望更改介面檔案中特定宣告的默認包裝,例如,你可能想要提供鉤子來捕獲 C++ 例外,添加斷言或為底層代碼生成器提供提示,本章介紹其中一些自定義技術,首先,對例外處理進行了討論,然后,描述了一種稱為“功能”的,更通用的自定義機制,

12.1 用 %exception 處理例外

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 <setjmp.h> library. Here is a minimalistic implementation that relies on the C preprocessor :

也可以使用 <setjmp.h> 庫將例外處理添加到 C 代碼中,這是一個依賴 C 前處理器的簡約實作:

/* File : except.c
   Just the declaration of a few global variables we're going to use */

#include <setjmp.h>
jmp_buf exception_buffer;
int exception_status;

/* File : except.h */
#include <setjmp.h>
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 SWIG_exception() function can also be used in typemaps.

SWIG_exception() 函式也可以用于型別映射,

12.2 物件所有權與 %newobject

A common problem in some applications is managing proper ownership of objects. For example, consider a function like this:

在某些應用程式中,一個常見的問題是正確地管理物件的所有權,例如,考慮如下函式:

Foo *blah() {
  Foo *f = new Foo();
  return f;
}

If you wrap the function blah(), SWIG has no idea that the return value is a newly allocated object. As a result, the resulting extension module may produce a memory leak (SWIG is conservative and will never delete objects unless it knows for certain that the returned object was newly created).

To fix this, you can provide an extra hint to the code generator using the %newobject directive. For example:

如果包裝函式 blah(),SWIG 不知道回傳值是新分配的物件,結果,生成的擴展模塊可能會產生記憶體泄漏(SWIG 是保守的,除非確定可以肯定回傳的物件是新創建的,否則從不洗掉物件),

為了解決這個問題,你可以使用 %newobject 指令為代碼生成器提供額外的提示,例如:

%newobject blah;
Foo *blah();

%newobject works exactly like %rename and %exception. In other words, you can attach it to class members and parameterized declarations as before. For example:

%newobject 的作業方式與 %rename%exception 完全相同,換句話說,你可以像以前一樣將其附加到類成員和引數化宣告中,例如:

%newobject ::blah();                   // Only applies to global blah
%newobject Object::blah(int, double);  // Only blah(int, double) in Object
%newobject *::copy;                    // Copy method in all classes
...

When %newobject is supplied, many language modules will arrange to take ownership of the return value. This allows the value to be automatically garbage-collected when it is no longer in use. However, this depends entirely on the target language (a language module may also choose to ignore the %newobject directive).

Closely related to %newobject is a special typemap. The newfree typemap can be used to deallocate a newly allocated return value. It is only available on methods for which %newobject has been applied and is commonly used to clean-up string results. For example:

當提供 %newobject 時,許多語言模塊將安排獲取回傳值的所有權,這樣就可以在不再使用該值時自動對其進行垃圾回收,但是,這完全取決于目標語言(語言模塊也可以選擇忽略 %newobject 指令),

%newobject 密切相關的是一個特殊的型別映射,newfree 型別映射可用于釋放新分配的回傳值,它僅在應用了 %newobject 的方法上可用,并且通常用于清理字串結果,例如:

%typemap(newfree) char * "free($1);";
...
%newobject strdup;
...
char *strdup(const char *s);

In this case, the result of the function is a string in the target language. Since this string is a copy of the original result, the data returned by strdup() is no longer needed. The "newfree" typemap in the example simply releases this memory.

As a complement to the %newobject, from SWIG 1.3.28, you can use the %delobject directive. For example, if you have two methods, one to create objects and one to destroy them, you can use:

在這種情況下,函式的結果是目標語言中的字串,由于該字串是原始結果的副本,因此不再需要 strdup() 回傳的資料,示例中的 newfree 型別映射僅釋放該記憶體,

作為對 SWIG 1.3.28 中 %newobject 的補充,你可以使用 %delobject 指令,例如,如果你有兩種方法,一種用于創建物件,另一種用于銷毀它們,則可以使用:

%newobject create_foo;
%delobject destroy_foo;
...
Foo *create_foo();
void destroy_foo(Foo *foo);

or in a member method as:

或者在成員方法中作為:

%delobject Foo::destroy;

class Foo {
public:
  void destroy() { delete this;}

private:
  ~Foo();
};

%delobject instructs SWIG that the first argument passed to the method will be destroyed, and therefore, the target language should not attempt to deallocate it twice. This is similar to use the DISOWN typemap in the first method argument, and in fact, it also depends on the target language on implementing the 'disown' mechanism properly.

The use of %newobject is also integrated with reference counting and is covered in the C++ reference counted objects section.

Compatibility note: Previous versions of SWIG had a special %new directive. However, unlike %newobject, it only applied to the next declaration. For example:

%delobject 指示 SWIG 傳遞給該方法的第一個引數將被銷毀,因此,目標語言不應嘗試對其進行兩次分配,這類似于在第一個方法引數中使用 DISOWN 型別映射,實際上,它還取決于目標語言是否正確實作了 disown 機制,

%newobject 的使用也與參考計數集成在一起,并在 C++ 參考計數物件章節中進行了介紹,

注意兼容性:早期版本的 SWIG 具有特殊的 %new 指令,但是,與 %newobject 不同,它僅適用于下一個宣告,例如:

%new char *strdup(const char *s);

For now this is still supported but is deprecated.

How to shoot yourself in the foot: The %newobject directive is not a declaration modifier like the old%new directive. Don't write code like this:

目前,仍支持此功能,但已棄用,

如何射擊自己的腳%newobject 指令與舊的 %new 指令不同,它不是一個宣告修飾符,不要寫這樣的代碼:

%newobject
char *strdup(const char *s);

The results might not be what you expect.

結果可能不是你所期望的,

12.3 功能與 %feature 指令

Both %exception and %newobject are examples of a more general purpose customization mechanism known as "features." A feature is simply a user-definable property that is attached to specific declarations. Features are attached using the %feature directive. For example:

%exception%newobject 都是更通用的自定義機制(稱為“功能”)的示例,功能只是附加到特定宣告的用戶可定義的屬性,功能使用 %feature 指令附加,例如:

%feature("except") Object::allocate {
  try {
    $action
  }
  catch (MemoryError) {
    croak("Out of memory");
  }
}

%feature("new", "1") *::copy;

In fact, the %exception and %newobject directives are really nothing more than macros involving %feature:

實際上 %exception%newobject 就是包含 %feature 的宏:

#define %exception %feature("except")
#define %newobject %feature("new", "1")

The name matching rules outlined in the Ambiguity resolution and renaming section applies to all %feature directives. In fact the %rename directive is just a special form of %feature. The matching rules mean that features are very flexible and can be applied with pinpoint accuracy to specific declarations if needed. Additionally, if no declaration name is given, a global feature is said to be defined. This feature is then attached to every declaration that follows. This is how global exception handlers are defined. For example:

消歧義析和重命名章節中概述的名稱匹配規則適用于所有 %feature 指令,實際上,%rename 指令只是 %feature 的一種特殊形式,匹配規則意味著功能非常靈活,如果需要,可以精確地將其應用于特定宣告,此外,如果未給出宣告名稱,則稱已定義了全域功能,然后,此功能將附加到隨后的每個宣告,這就是定義全域例外處理程式的方式,例如:

/* Define a global exception handler */
%feature("except") {
  try {
    $action
  }
  ...
}

... bunch of declarations ...

The %feature directive can be used with different syntax. The following are all equivalent:

%feature 指令有不同的語法,以下都是等價的:

%feature("except") Object::method { $action };
%feature("except") Object::method %{ $action %};
%feature("except") Object::method " $action ";
%feature("except", "$action") Object::method;

The syntax in the first variation will generate the { } delimiters used whereas the other variations will not.

第一個變體中的語法將生成使用的 { } 分隔符,而其他變體則不,

12.3.1 功能屬性

The %feature directive also accepts XML style attributes in the same way that typemaps do. Any number of attributes can be specified. The following is the generic syntax for features:

%feature 指令也以與型別映射相同的方式接受 XML 樣式的屬性,可以指定任意數量的屬性,以下是功能的通用語法:

%feature("name", "value", attribute1="AttributeValue1") symbol;
%feature("name", attribute1="AttributeValue1") symbol {value};
%feature("name", attribute1="AttributeValue1") symbol %{value%};
%feature("name", attribute1="AttributeValue1") symbol "value";

More than one attribute can be specified using a comma separated list. The Java module is an example that uses attributes in %feature("except"). The throws attribute specifies the name of a Java class to add to a proxy method's throws clause. In the following example, MyExceptionClass is the name of the Java class for adding to the throws clause.

可以使用逗號分隔的串列來指定多個屬性,Java 模塊是使用 %feature("except") 中的屬性的示例,throws 屬性指定要添加到代理方法 throw 子句中 Java 類的名稱,在下面的示例中,MyExceptionClass 是要添加到 throw 子句中的 Java 類的名稱,

%feature("except", throws="MyExceptionClass") Object::method {
  try {
    $action
  } catch (...) {
    ... code to throw a MyExceptionClass Java exception ...
  }
};

Further details can be obtained from the Java exception handling section.

更多細節可以從 Java 例外處理章節獲得,

12.3.2 功能標志

Feature flags are used to enable or disable a particular feature. Feature flags are a common but simple usage of %feature and the feature value should be either 1 to enable or 0 to disable the feature.

功能標志用于啟用或禁用特定功能,功能標志是 %feature 常見但簡單的用法,值應為 1 則啟用,為 0 則禁用功能,

%feature("featurename")          // enables feature
%feature("featurename", "1")     // enables feature
%feature("featurename", "x")     // enables feature
%feature("featurename", "0")     // disables feature
%feature("featurename", "")      // clears feature

Actually any value other than zero will enable the feature. Note that if the value is omitted completely, the default value becomes 1, thereby enabling the feature. A feature is cleared by specifying no value, see Clearing features. The %immutable directive described in the Creating read-only variables section, is just a macro for %feature("immutable"), and can be used to demonstrates feature flags:

實際上,除 0 以外的任何值都將啟用該功能,請注意,如果該值被完全省略,則默認值為 1,從而啟用該功能,通過不指定任何值來清除功能,請參閱清除功能章節,在創建只讀變數章節中描述的 %immutable 指令只是 %feature("immutable") 的宏,可以用來演示功能標記:

                                // features are disabled by default
int red;                        // mutable

%feature("immutable");          // global enable
int orange;                     // immutable

%feature("immutable", "0");     // global disable
int yellow;                     // mutable

%feature("immutable", "1");     // another form of global enable
int green;                      // immutable

%feature("immutable", "");      // clears the global feature
int blue;                       // mutable

Note that features are disabled by default and must be explicitly enabled either globally or by specifying a targeted declaration. The above intersperses SWIG directives with C code. Of course you can target features explicitly, so the above could also be rewritten as:

請注意,默認情況下禁用功能,必須在全域范圍內或通過指定目標宣告來顯式啟用功能,上面的代碼將 SWIG 指令插入 C 代碼中,當然,你可以明確地定位功能,因此上面的內容也可以重寫為:

%feature("immutable", "1") orange;
%feature("immutable", "1") green;
int red;                        // mutable
int orange;                     // immutable
int yellow;                     // mutable
int green;                      // immutable
int blue;                       // mutable

The above approach allows for the C declarations to be separated from the SWIG directives for when the C declarations are parsed from a C header file. The logic above can of course be inverted and rewritten as:

當從 C 頭檔案決議 C 宣告時,上述方法允許將 C 宣告與 SWIG 指令分開,上面的邏輯當然可以顛倒并重寫為:

%feature("immutable", "1");
%feature("immutable", "0") red;
%feature("immutable", "0") yellow;
%feature("immutable", "0") blue;
int red;                        // mutable
int orange;                     // immutable
int yellow;                     // mutable
int green;                      // immutable
int blue;                       // mutable

As hinted above for %immutable, most feature flags can also be specified via alternative syntax. The alternative syntax is just a macro in the swig.swg Library file. The following shows the alternative syntax for the imaginary featurename feature:

就像上面對 %immutable 的提示一樣,大多數功能標志也可以通過其他語法來指定,替代語法只是 swig.swg 庫檔案中的宏,下面顯示了虛構的 featurename 功能的替代語法:

%featurename       // equivalent to %feature("featurename", "1") ie enables feature
%nofeaturename     // equivalent to %feature("featurename", "0") ie disables feature
%clearfeaturename  // equivalent to %feature("featurename", "")  ie clears feature

The concept of clearing features is discussed next.

接下來介紹清除功能的概念,

12.3.3 清除功能

A feature stays in effect until it is explicitly cleared. A feature is cleared by supplying a %feature directive with no value. For example %feature("name", ""). A cleared feature means that any feature exactly matching any previously defined feature is no longer used in the name matching rules. So if a feature is cleared, it might mean that another name matching rule will apply. To clarify, let's consider the except feature again (%exception):

在明確將其清除之前,功能一直有效,通過提供無值的 %feature 指令可以清除功能,例如 %feature("name", ""),清除的功能意味著名稱匹配規則中不再使用與先前定義的功能完全匹配的任何功能,因此,如果一項功能被清除,則可能意味著將應用另一個名稱匹配規則,為了澄清,讓我們再次考慮 except 功能(%exception):

// Define global exception handler
%feature("except") {
  try {
    $action
  } catch (...) {
    croak("Unknown C++ exception");
  }
}

// Define exception handler for all clone methods to log the method calls
%feature("except") *::clone() {
  try {
    logger.info("$action");
    $action
  } catch (...) {
    croak("Unknown C++ exception");
  }
}

... initial set of class declarations with clone methods ...

// clear the previously defined feature
%feature("except", "") *::clone();

... final set of class declarations with clone methods ...

In the above scenario, the initial set of clone methods will log all method invocations from the target language. This specific feature is cleared for the final set of clone methods. However, these clone methods will still have an exception handler (without logging) as the next best feature match for them is the global exception handler.

Note that clearing a feature is not always the same as disabling it. Clearing the feature above with %feature("except", "") *::clone() is not the same as specifying %feature("except", "0") *::clone(). The former will disable the feature for clone methods - the feature is still a better match than the global feature. If on the other hand, no global exception handler had been defined at all, then clearing the feature would be the same as disabling it as no other feature would have matched.

Note that the feature must match exactly for it to be cleared by any previously defined feature. For example the following attempt to clear the initial feature will not work:

在上述情況下,初始的克隆方法將記錄來自目標語言的所有方法呼叫,最后一組克隆方法將清除此特定功能,但是,這些克隆方法仍將具有例外處理程式(不進行日志記錄),因為它們的下一個最佳功能匹配是全域例外處理程式,

請注意,清除功能并不總是與禁用功能相同,用 %feature("except", "0") *::clone() 清除上面的功能與指定 %feature("except", "0") *::clone() 不同,前者將禁用克隆方法的功能,該功能仍然比全域功能更好,另一方面,如果根本沒有定義全域例外處理程式,則清除該功能與禁用該功能相同,因為沒有其他功能可以匹配,

請注意,該功能必須完全匹配才能被任何先前定義的功能清除,例如,以下清除初始功能的嘗試將無效:

%feature("except") clone() { logger.info("$action"); $action }
%feature("except", "") *::clone();

but this will:

但是這可以:

%feature("except") clone() { logger.info("$action"); $action }
%feature("except", "") clone();

SWIG provides macros for disabling and clearing features. Many of these can be found in the swig.swglibrary file. The typical pattern is to define three macros; one to define the feature itself, one to disable the feature and one to clear the feature. The three macros below show this for the "except" feature:

SWIG 提供了用于禁用和清除功能的宏,其中許多可以在 swig.swg 庫檔案中找到,典型的模式是定義三個宏,一種是定義功能本身,一種是禁用功能,另一種是清除功能,下面的三個宏針對 except 功能顯示了這一點:

#define %exception      %feature("except")
#define %noexception    %feature("except", "0")
#define %clearexception %feature("except", "")

12.3.4 功能與默認引數

SWIG treats methods with default arguments as separate overloaded methods as detailed in the default arguments section. Any %feature targeting a method with default arguments will apply to all the extra overloaded methods that SWIG generates if the default arguments are specified in the feature. If the default arguments are not specified in the feature, then the feature will match that exact wrapper method only and not the extra overloaded methods that SWIG generates. For example:

SWIG 將具有默認引數的方法視為單獨的多載方法,如默認引數章節中所述,如果在功能中指定了默認引數,則以默認引數為目標的任何 %feature 都將應用于 SWIG 生成的所有額外多載方法,如果未在功能中指定默認引數,則功能將僅與該完全包裝方法匹配,而不與 SWIG 生成的額外多載方法匹配,例如:

%feature("except") hello(int i=0, double d=0.0) { ... }
void hello(int i=0, double d=0.0);

will apply the feature to all three wrapper methods, that is:

將把功能應用于所有三個包裝器方法,也就是:

void hello(int i, double d);
void hello(int i);
void hello();

If the default arguments are not specified in the feature:

如果功能中沒有指定默認引數:

%feature("except") hello(int i, double d) { ... }
void hello(int i=0, double d=0.0);

then the feature will only apply to this wrapper method:

那么功能只應用這個包裝器方法:

void hello(int i, double d);

and not these wrapper methods:

而不是這些方法:

void hello(int i);
void hello();

If compactdefaultargs are being used, then the difference between specifying or not specifying default arguments in a feature is not applicable as just one wrapper is generated.

Compatibility note: The different behaviour of features specified with or without default arguments was introduced in SWIG-1.3.23 when the approach to wrapping methods with default arguments was changed.

如果使用 compactdefaultargs,則僅在生成一個包裝器時,在功能中指定或不指定默認引數之間的區別不適用,

注意兼容性:當更改使用默認引數包裝方法的方法時,在 SWIG-1.3.23 中引入了使用或不使用默認引數指定的功能的不同行為,

12.3.5 功能示例

As has been shown earlier, the intended use for the %feature directive is as a highly flexible customization mechanism that can be used to annotate declarations with additional information for use by specific target language modules. Another example is in the Python module. You might use %featureto rewrite proxy/shadow class code as follows:

如前所述,%feature 指令的預期用途是一種高度靈活的自定義機制,可用于為宣告加上附加資訊以供特定目標語言模塊使用,另一個示例在 Python 模塊中,你可以使用 %feature 來重寫代理/影子類代碼,如下所示:

%module example
%rename(bar_id) bar(int, double);

// Rewrite bar() to allow some nice overloading

%feature("shadow") Foo::bar(int) %{
def bar(*args):
    if len(args) == 3:
        return apply(examplec.Foo_bar_id, args)
    return apply(examplec.Foo_bar, args)
%}

class Foo {
public:
  int bar(int x);
  int bar(int x, double y);
}

Further details of %feature usage is described in the documentation for specific language modules.

%feature 用法的更多詳細資訊在特定語言模塊的檔案中進行了描述,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/4991.html

標籤:C++

上一篇:基礎練習(01)閏年判斷

下一篇:C 實戰練習題目67

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more