2016-09-30 8 views
1

私はRcppフリーのC/C++エクステンション(ライセンスのために)として書き直さなければならないRcppコードをたくさん持っていて、幸いにもそれは恐ろしいほど痛いほどのものではありません。しかし、最もクリーンなコードを書くために、私はPROTECT/UNPROTECTを過度に使用していないことを確認したい。文書Writing R Extensionsは、「目に見えるものをすべて保護するのは良い考えではありません...」と述べていますので、私は義務づけようとしています。.Call引数を保護する必要がありますか?

ここで確認したいことがあります。 RのC拡張を書くすべての例を読むと、著者が渡された関数の引数を保護する例がたくさんありました。これはthis articleから取ったものです。

#include <R.h> 
#include <Rdefines.h> 
#include <string.h> 
SEXP helloC1(SEXP greeting) { 
  int i, vectorLength, stringLength; 
  SEXP result; 
  PROTECT(greeting = AS_CHARACTER(greeting)); 
  vectorLength = LENGTH(greeting); 
  PROTECT(result = NEW_INTEGER(vectorLength)); 
  for (i=0; i<vectorLength; i++) { 
    stringLength = strlen(CHAR(STRING_ELT(greeting, i))); 
    INTEGER(result)[i] = stringLength; 
  } 
  UNPROTECT(2); 
  return(result); 
} 

SEXPの挨拶が引数として渡され、作成者がすぐにそれを保護しました。しかし、Writing R Extensionsから私はこのビットに気づいた:

Rは既に使用されているとわかっているオブジェクトには必要ありません。特に、これは関数の引数に適用されます。

したがって、作成者が渡された引数を保護するこれらのコード例がトリミングされる可能性があるかどうかを誰かに教えてもらえますか?この場合、私は自分のコードをもっときれいにすることができます。

+0

あなたは関数の引数を 'PROTECT 'する必要はないという前提で、(正しい)(http://adv-r.had.co.nz/C-interface.html)です。 – hrbrmstr

+0

@hrbrmstr投稿が回答になる前に[r-faq]タグを追加する理由は何ですか? –

+1

[こちら](http://adv-r.had.co.nz/C-interface.html#c-vectors)の件名にもう少し詳しい情報があります。 – nrussell

答えて

4

入力引数を保護する必要はありませんが、あなたが1つのビットを誤解している - それは、入力引数greetingではありません保護されていますが、新しいSEXPが保護されているAS_CHARACTER(greeting)によって生成されています。

greeting変数はすぐに再割り当てされるので、それは少し混乱だが、効果的にあなたは今SEXP新ブランドを指すgreetingを持っており、それがガベージコレクタからの保護を必要とする新しいオブジェクトです。

+0

あなたは正しいと思います。私は、清潔さを念頭に置いて、自分の意見を守っていましたが、私たちのチームはセグメンテーションを開始したようです。疑いの余地があるときは、物事をさらに守るだけだと思います。 –

9

私は、私はあなたが(良い)弁護士が必要な場合があります(これはそのライセンスに)RcppフリーのC/C++拡張

としてリライトする必要がありRcppコードの束を持っています。 R自体はRcppと同じライセンスの下にあります。したがって、Rcppを回避することは、リンクされた集約がまだGPL 2以降であるため、ほとんどあなたを得られません。

編集:ちょうどキックのために、ここでは機能のより単純で短い実装が2つあります。読みやすく使いやすいかもしれません。 Rcppがそれをすべて処理するので、ユーザー空間ではPROTECTのダンスはありません。

#include <Rcpp.h> 

using namespace Rcpp; 

// [[Rcpp::export]] 
IntegerVector helloC2(CharacterVector v) { 
    IntegerVector res(v.size()); 
    for (int i=0; i<v.size(); i++) { 
    res[i] = strlen(v[i]); 
    } 
    return(res); 
} 

// [[Rcpp::export]] 
IntegerVector helloC3(CharacterVector v) { 
    return wrap(sapply(v, strlen)); 
} 

これらは、あなたの関数の同じ出力を生成します(もちろん)。

まず、あなた:

R> system("cd /tmp && R CMD SHLIB prot.c") 
R> dyn.load("/tmp/prot.so") 
R> .Call("helloC1", c("the", "quick", "brown", "fox")) 
[1] 3 5 5 3 
R> 

次に、鉱山:

R> Rcpp::sourceCpp("/tmp/prot.cpp") 
R> helloC2(c("the", "quick", "brown", "fox")) 
[1] 3 5 5 3 
R> helloC3(c("the", "quick", "brown", "fox")) 
[1] 3 5 5 3 
R> 
+0

さて、いいえ、私は弁護士のことであなたと違うように頼む必要があります。 (そして、はい、私たちは多くの弁護士とソフトウェア監査を行う人々を抱えており、私が自分自身で決めたものに旗を立てました)。同様の議論を見ることができます(http://softwareengineering.stackexchange.com/questions/254737/ rcpp-dependent-package-require-a-gpl-license)を使用してください。 R "スクリプト"には任意のライセンスが付与できますが、Rcppライセンスにリンクするとコードが汚染され、当社が保護する必要がある知的財産があります。 –

+3

i)Rcppライセンスは機能です。したがって、Rによって使用されるライセンスと同じになることもあります。したがって、ii)Rcppの有無にかかわらず、Rにリンクすると、あなたはまだGPLに拘束されます。したがって、... iii)Rcppはライセンス/使用条件について何も変えず、コーディングを容易にします。 –

+0

[link](http://softwareengineering.stackexchange.com/questions/254737/does-an-rcpp-dependent-package-require-a-gpl-license)に感謝します。 2番目の答えは間違っているので、私はそこにフォローアップします。受け入れられた答えは正しいです。 –

関連する問題