SWIG 3 中文手冊——13. 約定

来源:https://www.cnblogs.com/xuruilong100/archive/2020/06/29/13210798.html

13 約定 A common problem that arises when wrapping C libraries is that of maintaining reliability and checking for errors. The fact of the matter is tha ...


13 約定

A common problem that arises when wrapping C libraries is that of maintaining reliability and checking for errors. The fact of the matter is that many C programs are notorious for not providing error checks. Not only that, when you expose the internals of an application as a library, it often becomes possible to crash it simply by providing bad inputs or using it in a way that wasn't intended.

This chapter describes SWIG's support for software contracts. In the context of SWIG, a contract can be viewed as a runtime constraint that is attached to a declaration. For example, you can easily attach argument checking rules, check the output values of a function and more. When one of the rules is violated by a script, a runtime exception is generated rather than having the program continue to execute.

包裝 C 庫時出現的常見問題是維護可靠性和檢查錯誤。事實是,許多 C 程式因不提供錯誤檢查而臭名昭著。不僅如此,當你將應用程式的內部結構公開為一個庫時,通常可能會因提供錯誤的輸入或以非預期的方式使用它而使其崩潰。

本章介紹 SWIG 對軟體約定的支持。在 SWIG 的上下文中,約定可以視為附加到聲明的運行時約束。例如,你可以輕鬆地附加參數檢查規則,檢查函數的輸出值等等。如果腳本違反了其中一個規則,則會生成運行時異常,而不是讓程式繼續執行。

13.1 %contract 指令

Contracts are added to a declaration using the %contract directive. Here is a simple example:

使用 %contract 指令將約定添加到聲明中。這是一個簡單的示例:

%contract sqrt(double x) {
require:
  x >= 0;
ensure:
  sqrt >= 0;
}

...
double sqrt(double);

In this case, a contract is being added to the sqrt() function. The %contract directive must always appear before the declaration in question. Within the contract there are two sections, both of which are optional. The require: section specifies conditions that must hold before the function is called. Typically, this is used to check argument values. The ensure: section specifies conditions that must hold after the function is called. This is often used to check return values or the state of the program. In both cases, the conditions that must hold must be specified as boolean expressions.

In the above example, we're simply making sure that sqrt() returns a non-negative number (if it didn't, then it would be broken in some way).

Once a contract has been specified, it modifies the behavior of the resulting module. For example:

在這種情況下,將約定添加到 sqrt() 函數中。%contract 指令必須始終出現在相關聲明之前。約定中有兩個部分,兩者都是可選的。require: 部分指定了在調用函數之前必須滿足的條件。通常,它用於檢查參數值。ensure: 部分指定了在調用函數後必須滿足的條件。通常用於檢查返回值或程式狀態。在這兩種情況下,必須滿足的條件都必須指定為布爾表達式。

在上面的示例中,我們只是確保 sqrt() 返回一個非負數(如果不返回,那麼它將以某種方式被破壞)。

指定約定後,它將修改結果模塊的行為。例如:

>>> example.sqrt(2)
1.4142135623730951
>>> example.sqrt(-2)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
RuntimeError: Contract violation: require: (arg1>=0)
>>>

13.2 %contract 與類

The %contract directive can also be applied to class methods and constructors. For example:

%contract 指令也可以應用於類方法和構造函數。例如:

%contract Foo::bar(int x, int y) {
require:
  x > 0;
ensure:
  bar > 0;
}

%contract Foo::Foo(int a) {
require:
  a > 0;
}

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

The way in which %contract is applied is exactly the same as the %feature directive. Thus, any contract that you specified for a base class will also be attached to inherited methods. For example:

%contract 的應用方式與 %feature 指令完全相同。因此,你為基類指定的任何約定也將附加到繼承的方法。例如:

class Spam : public Foo {
public:
  int bar(int, int);    // Gets contract defined for Foo::bar(int, int)
};

In addition to this, separate contracts can be applied to both the base class and a derived class. For example:

除此之外,可以將單獨的約定同時應用於基類和派生類。例如:

%contract Foo::bar(int x, int) {
require:
  x > 0;
}

%contract Spam::bar(int, int y) {
require:
  y > 0;
}

class Foo {
public:
  int bar(int, int);   // Gets Foo::bar contract.
};

class Spam : public Foo {
public:
  int bar(int, int);   // Gets Foo::bar and Spam::bar contract
};

When more than one contract is applied, the conditions specified in a "require:" section are combined together using a logical-AND operation. In other words conditions specified for the base class and conditions specified for the derived class all must hold. In the above example, this means that both the arguments to Spam::bar must be positive.

當應用多個約定時,使用邏輯與運算將 require: 部分中指定的條件組合在一起。換句話說,為基類指定的條件和為派生類指定的條件都必須成立。在上面的示例中,這意味著 Spam::bar 的兩個參數都必須為正。

13.3 約定集成與 %aggregate_check

Consider an interface file that contains the following code:

考慮包含以下代碼的介面文件:

#define  UP     1
#define  DOWN   2
#define  RIGHT  3
#define  LEFT   4

void move(SomeObject *, int direction, int distance);

One thing you might want to do is impose a constraint on the direction parameter to make sure it's one of a few accepted values. To do that, SWIG provides an easy to use macro %aggregate_check() that works like this:

你可能想做的一件事是對 direction 參數施加約束,以確保它是少數幾個可接受的值之一。為此,SWIG 提供了一個易於使用的巨集 %aggregate_check(),其工作方式如下:

%aggregate_check(int, check_direction, UP, DOWN, LEFT, RIGHT);

This merely defines a utility function of the form

只是定義一個工具函數

int check_direction(int x);

That checks the argument x to see if it is one of the values listed. This utility function can be used in contracts. For example:

這將檢查參數 x 以查看其是否為列出的值之一。可以在約定中使用此實用程式函數。例如:

%aggregate_check(int, check_direction, UP, DOWN, RIGHT, LEFT);

%contract move(SomeObject *, int direction, in) {
require:
  check_direction(direction);
}

#define  UP     1
#define  DOWN   2
#define  RIGHT  3
#define  LEFT   4

void move(SomeObject *, int direction, int distance);

Alternatively, it can be used in typemaps and other directives. For example:

另外,它可以在類型映射和其他指令中使用。例如:

%aggregate_check(int, check_direction, UP, DOWN, RIGHT, LEFT);

%typemap(check) int direction {
  if (!check_direction($1)) SWIG_exception(SWIG_ValueError, "Bad direction");
}

#define  UP     1
#define  DOWN   2
#define  RIGHT  3
#define  LEFT   4

void move(SomeObject *, int direction, int distance);

Regrettably, there is no automatic way to perform similar checks with enums values. Maybe in a future release.

遺憾的是,沒有自動的方法可以對枚舉值執行類似的檢查。也許在將來的版本中可以。

13.4 註意事項

Contract support was implemented by Songyan (Tiger) Feng and first appeared in SWIG-1.3.20.

約定支持由 Songyan(Tiger)Feng 實施,並首次出現在 SWIG-1.3.20 中。


您的分享是我們最大的動力!

更多相關文章
  • 基於Nexus搭建私服 1. 工作流程 2. 倉庫類型 hosted 私服倉庫 proxy倉庫 遠程倉庫 group倉庫 組倉庫,裡面可以設置組合多個倉庫。按順序獲取jar。 3. 預設倉庫 安裝好了Nexus後,會內置幾個maven的預設倉庫。可自定義倉庫。 maven-central proxy ...
  • 1 前言 相信不少人聽過這麼一句話: 人類的本質是復讀機。 在軟體開發領域也一樣,我們總是想尋找更好地方式複製優秀的邏輯或系統。最核心的方法是抽取通用邏輯和組件,把差異化的東西介面化或配置化,達到復用的效果。如Java的Build Once, Run Everywhere,還有Spring的強大的抽 ...
  • 引用原文 原文鏈接 http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang/ 問題描述 直入本文要描述的問題:網站流量上來了,高併發負載是不可避免滴問題了,當服務端需要處理大量耗時的任務時,我們一般都會考 ...
  • 一、可移植類型舉例 1.系統不支持“精確寬度整數類型”怎麼辦? 最小寬度類型:一些類型名保證所表示的類型一定是至少有指定寬度的最小整數類型。 使用上述定義的類型,例如:int_least8_t是可以容納8位有符號整數值類型中的寬度最小的類型的一個別名,如果某系統的最小整數類型是16位,可能不會定義i ...
  • Reactor 操作符 上篇文章我們將 Flux 和 Mono 的操作符分了 11 類,我們來繼續學習轉換類操作符的第 2 篇。 轉換類操作符 轉換類的操作符數量最多,平常過程中也是使用最頻繁的。 Flux#concatMap 將響應式流中元素順序轉換為目標類型的響應式流,之後再將這些流連接起來。該 ...
  • pom.xml中引入 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.2</version> </dependency> 在applicati ...
  • 1.判斷提交方式 if(request.getMethod().equals("POST")) 2.返回json @ResponseBody 3.限定請求方式 @RequestMapping(value="/login",method= RequestMethod.POST) 4.session / ...
  • 安裝typora 下載地址:https://www.typora.io/ 找到配置文件 picgo 的預設配置文件為~/.picgo/config.json。其中~為用戶目錄。不同系統的用戶目錄不太一樣。 linux 和 macOS 均為~/.picgo/config.json。 windows 則 ...
一周排行
  • C#6.0新特性 C#7.0新特性 C#8.0新特性 ...
  • out變數 可以直接在方法中使用out申明變數 int.TryParse("123", out var result); 元組 元組的申明 var alphaBetaStart = (alpha: "a", beta: "b"); Console.WriteLine($"{alphaBetaStar ...
  • 在我們的項目中,通常會把數據存儲到關係型資料庫中,比如Oracle,SQL Server,Mysql等,但是關係型資料庫對於併發的支持並不是很強大,這樣就會造成系統的性能不佳,而且存儲的數據多為結構化數據,對於非結構數據(比如文本)和半結構化數據(比如JSon) 就顯得不夠靈活,而非關係型資料庫則很 ...
  • 這幾天終於弄懂了async和await的模式,也搞明白了一直在心裡面積壓著的許多問題,所以寫一篇博客來和大家分享一下。 關於非同步機制我認為只要記住的以下幾點,就可以弄明白了: 1.我認為async和awwait兩個修飾符中最關鍵的是await,async是由於方法中包含await修飾符之後才在方法定 ...
  • 實現WCF的步驟如下: 設計服務協議 實現服務協議 配置服務 托管服務 生成客戶端(這步可有可無) 設計或定義服務協議要麼使用介面,要麼使用類。建議介面,使用介面好處一堆例如修改介面的實現,但是服務協定有無需改變。 設計服務協議,介面上使用 ServiceContractAttribute ,方法上 ...
  • 什麼鬼,我的CPF快寫好了,你居然也要搞跨平臺UI框架?什麼Maui? 之前怎麼不早說要搞跨平臺UI框架呢?看到谷歌搞flutter眼紅了?明年年底發佈?又搞這種追別人屁股的爛事情。 什麼MVU模式?模仿Dart?用C#代碼直接寫UI的模式和我的CPF很像啊。 當初我考慮過XML,Json來描述UI ...
  • 寫在前面 Docker作為開源的應用容器引擎,可以讓我們很輕鬆的構建一個輕量級、易移植的容器,通過Docker方式進行持續交付、測試和部署,都是極為方便的,並且對於我們開發來說,最直觀的優點還是解決了日常開發中的環境配置與部署環境配置上的差異所帶來的種種疑難雜症,從此推脫產品的措辭也少了——“我電腦 ...
  • 一、前言 回顧:認證授權方案之授權初識 從上一節中,我們在對授權系統已經有了初步的認識和使用,可以發現,asp.net core為我們提供的授權策略是一個非常強大豐富且靈活的認證授權方案,能夠滿足大部分的授權場景。 在ConfigureServices中配置服務:將授權服務添加到容器 public ...
  • 項目背景: 工作之餘兼職一家公司(方向是工業4.0)給做IM系統,主要功能包括:文字、 圖片、文件傳輸、遠程協助、視頻語音等等。這些功能都是基於群會話, 比如工廠操作工人遇到問題,請求遠程專家,這個初級專家不能解決問題,會邀請一個高級專家進來解決。開發過程中主要遇到的問題是視頻和語音這一塊,像其他的... ...
  • 基礎概念 Microsoft中間語言(MSIL),也成為通用中間語言(CIL),是一組與平臺無關的指令,由特定於語言的編譯器從源代碼生成。MSIL是獨立於平臺的,因此,他可以在任何公共語言基礎架構支持特定的環境上執行。 通過JIT編譯器將MSIL轉換為特定電腦環境的特定機器代碼。這是在執行MSIL ...