PerlでInline Cを使った配列の引渡し

このQ&Aのポイント
  • Perlで繰り返し計算を高速化するためにInline Cを使用してC言語のサブルーチンを作成します。
  • しかし、PerlからCへの巨大配列の引渡し方法が分からず困っています。
  • リファレンスで渡してポインタで受け取ることもできないため、助けが必要です。
回答を見る
  • ベストアンサー

PerlでInline Cを使った配列の引渡し

Perlで繰り返し計算をする部分を高速化しようとInline Cを使ってC言語のサブルーチンを作りました。 C言語単体なら、巨大な配列はポインタを使って引き渡すのですが。 Inline Cを使って、PerlからCへの巨大配列の引渡し方法が分かりません(><; 以下のように、リファレンスで渡してポインタで受け取る事もできないし。。。助けてください use Inline C; my @data; for(my $t=0;$t<=10000000;$t++){ $data[$t]=$t; } # C言語による処理 my $x = my_function_1(\@data); print "0から10の合計は$x\n"; __END__ __C__ // サブルーチン_1 long my_function_1(long *data){ long t; long t1=0; for(t=0;t<=10000000;t++){ t1=t1+data[t]; } return t1; }

  • Perl
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

表示がくずれるので、空白2文字を全角空白にしていることに注意。 なお、 0 .. 10000000 の和は long で表現できないので、 double に加算しています。 #!/usr/bin/perl use strict; use warnings; use feature 'say'; use Inline C => 'DATA'; my @data = (0 .. 10000000); my $ret = add(\@data); say $ret; __DATA__ __C__ #include <stdio.h> double add(SV* array_ref) {   int i;   int len;   double sum;   AV *av_ptr;   SV **num_ptr;   sum = 0;   av_ptr = (AV*)SvRV(array_ref);   len = av_len(av_ptr) + 1;   for (i = 0; i < len; i++) {     num_ptr = av_fetch(av_ptr, i, 0);     sum += SvIV(*num_ptr);   }   return sum; }

WEB_scientist
質問者

お礼

ありがとうございます。調べる取っ掛かりが掴めました! 以下の様な感じで実装してみました。 use Inline C; my @data; for(my $t=0;$t<=10000000;$t++){  $data[$t]=$t; } # C言語による処理 my $x = my_function_1(@data); print "合計は$x\n"; __END__ __C__ // サブルーチン_1 double my_function_1(long value, ...){  Inline_Stack_Vars;  long t;  double t1=0;  for(t=0;t<=10000000;t++){    t1=t1+SvIV(Inline_Stack_Item(t));  }  return t1; }

関連するQ&A

  • Perlのサブルーチンで連想配列(ハッシュ)を渡す

    Perlのサブルーチンで連想配列(ハッシュ)を渡す方法 -------------------------------------- $str=rep::replace(%A,$B,@C); -------------------------------------- sub refidrep ( \%\$\@ ){ my(%A,$B,@C)=(@_); } -------------------------------------- では、上手くいきませんでした。 どのようにしたら、連想配列をサブルーチンに渡せるのでしょうか? 分かる方いらっしゃいましたらご教授ください。

    • ベストアンサー
    • Perl
  • perlで配列のポインタをdllに渡すには?

    Active Perlの最新版(x86)を使っています。 C言語側で、 //配列の先頭要素へのポインタと配列の要素数を渡すと、要素の平均を整数で返す関数 int avr(int *array,int kazu) { int value=0; for(int i=0;i<kazu;i++) { value+=*(array+i); } return value/kazu; } などと書いて、avr.dllとしてビルドしたものを(モジュール定義はdefファイルにて指定)、 use Win32::API; my $function = Win32::API->new("avr", "avr", "PN", "N"); @array=(1,2,3,4,5); $avr=$function->Call(\@array,5); print "Content-type: text/html\n\n"; print $avr; と使ってみたのですが、出力値が期待の「3」ではなく、-123343252とか435893497などの無茶苦茶な数値になってしまいます。 配列のポインタの渡し方が違うのかとは思いますが、どう書いたら良いのか分からない状況です。 一応、他のプログラムからこのdllを使うと、正常動作するようです。

    • ベストアンサー
    • Perl
  • 【Perl】サブルーチンから多次元配列を戻したい

    【Perl】サブルーチンから多次元配列を戻したい サブルーチン内で作った2次元配列と1つの変数(例:@listと$i)をリターンしたいのですが、どのようにすれば良いでしょうか? ↓サブルーチン(calc) return (@list, $i); ↓メイン my $a = 12; my (@list, $i) = &calc($a); 間違っていると思いますが、現時点でのプログラムを一部書きました。 ご回答よろしくお願いします!

    • ベストアンサー
    • Perl
  • c言語で配列を返したい

    自分がc言語で書いているプログラムの関数で次のようなものがあるのですが、 int CTR(int data[], int* key, long long t){ int buf[sizeof(data)]; int tmp[16]; int bytesoft[128]; int i,j; KeyExpansion(key); for(i=0;i<sizeof(data);i+=16){ for(j=0;j<16;j++){ if(j<sizeof(bytesoft)) tmp[16-j-1]=bytesoft[sizeof(bytesoft)-j-1]; else tmp[16-j-1]=0; } Cipher(data); for(j=0;j<16;j++){ buf[i+j] ^= data[i+j]; } t=t+1; } return buf; } 配列bufを返すためには、ポインタを用いればいいということは調べて分かったのですが具体的にどのように書き換えればいいかよくわかりません。 どなたかご教授いただけないでしょうか?

  • Perlのリファレンスについて

    只今、Perlを勉強中なのですがリファレンスについてご質問させて頂ます。 Perlのリファレンスについて自分でも調べてみたのですが、いまいち使い方や使うメリットがよくわかりません。 どなたかわかりやすいサンプルなどと一緒に教えて頂けないでしょうか。 どういった場面で、どのように使うと便利なのかがわかりません。 そもそもリファレンスは積極的に使うべきものなのでしょうか? Perlのオブジェクト指向で使うものなのでしょうか? C言語のポインタと似てる、と説明されてもC言語は全く知らないのでイメージがつきません。 素人でもわかるようにご教授、またはサイトの紹介をお願い致します。

    • ベストアンサー
    • Perl
  • Perlは戻り値で、ハッシュや配列を正しく返さないのでしょうか?

    Perlは戻り値で、ハッシュや配列を正しく返さないのでしょうか? 返せるように見えて実際は、歯抜けのデータなど、不安定で使い物になりません。 よって、リファレンスでスカラー値で利用するのが正論でしょうか? $a = ''; %b = (); @c = (); ○ return ($a, \$b, \$c); × retuen ($a, %b, @c); ○ my ($a, $b, $c) = aru_kansuu($hikkey, ('komori')); × my ($a, %b, @c) = aru_kansuu($hikkey, ('komori'));

    • ベストアンサー
    • Perl
  • サブルーチン Perl みたいに C言語 で使うには 

    いままで数年HPを運営していたためにCGIを開発する手段として、Perl言語を使用してきました。その後、あるきっかけでC言語をするようになり、理屈上PerlとC言語が似ていました。 いままで、Perlでは開発・デバッグ等を効率よくするためサブルーチンを他のファイルにパッケージファイルとして開発していました。非常に便利でこれがC言語でも同じく使えたらいいなとつくづく思っています。 Perl言語の例 main.cgi(本体のファイル) package.pl(パッケージファイル) 本体ほファイルで実行させ、実行の途中必要なサブルーチンをパッケージファイルから呼び出します。 呼び出すには、 %渡す値=&パッケージ名::サブルーチン名; 同じようにC言語でやるときはどのようにすればいいのでしょうか?

  • [perl]メソッドの引数で受け取った配列データを直接編集したい

    現在、業務でperlプログラムを書いてます。 perlを初めて2か月、プログラムは ほぼ初です。 よろしくおねがいします。 例えば以下のようなコードで、「sub_func」というメソッド内で「main」メソッド内の配列データを直接編集したいのですが、うまくいきません。 これは、引数で渡しているのは配列の「ポインタ」ではなく「リファレンス」であるため、「sub_func」というメソッド内で、新たに「array_ref」という配列の実態を作成してしまっているのだと認識しています。 そのため、「main」メソッドに戻ったタイミングではデータは元に戻ってしまうのだと思っています。 sub sub_func {    my ($self, $array_ref) = @_ ;    $array_ref = [4,5,6];   # returnはせずに、引数で指定したデータに格納したい } sub main {    my ($self) = @_ ;    # メソッドに渡すデータ    my $data = {       array => [1,2,3],    };    my $data2 = [1,2,3];    my @data3 = (1,2,3);    # メソッドの中で、$data->{array}を [4,5,6] に変えたいが・・・    $self->sub_func( $data->{array} );    $self->sub_func( $data2 );    $self->sub_func( \@data3 );    # この時点で、どれも [1,2,3] のまま } 私の認識は間違っているのでしょうか?? また、どのようにすれば配列の要素を別のメソッド内で編集できるのでしょうか?? 御助言をお願いします。

    • ベストアンサー
    • Perl
  • perlでの三次元配列の作り方

    perlで三次元配列をテキスト入力から作りたいのですが、例えば二次元配列の場合 foreach $line (@input) push @data, [split /[:]/, $line]; で@dataが二次元配列になるのですが、三次元配列の場合このあとに push @output, \@data; とするとリファレンスが同じであるためループをまわしてもうまく三次元になりませんよね。 解決法はありますでしょうか?

  • C++配列の型に関するC++規格について教えていただきたいです。

    C++配列の型に関するC++規格について教えていただきたいです。 以前にYahoo知恵袋でも質問しましたが、答えが得られませんでしたので、こちらでも質問させていただきたいと思います。 ※以下、質問になります。(分かり難いかも知れませんが宜しくお願い致します。) 環境は、Visual Studio 2010 (C++) です。 std::fill_n() で次のような警告がでましたので、調べていましたところ、 ...\xutility(2801): warning C4996: 'std::_Fill_n': Function call with parameters that may be unsafe - ... 次のような定義方法を見つけました、 typedef char (&std::tr1::_No)[1]; ↑このような定義方法があることを初めて知りました。 ちなみに、std::fill_n() は次のようになりました。 long data[32]; std::fill_n(data, 32, 0); ←正常 long* p_data = data; std::fill_n(p_data, 32, 0); ←warning long (&a_data)[32] = data; std::fill_n(a_data, 32, 0); ←正常 知りたいのは、配列を関数に渡すときに、 通常は、void func(long* pd); のようにポインタで渡すと思います。 また、void func(long pd[]); や void func(long pd[32]); もポインタの場合と同じになりますが、型保証がありません。 これはC++規格で規定されていることだと思います。 次のようにすると、型保証がされますが、この記法がC++の規格として規定されているかを知りたいです。 1. void func(long (&ad)[32]); // 関数呼び出しは、func(data); 2. void func(long (*pd)[32]); // 関数呼び出しは、func(&data); また、通常のポインタで配列を渡すことを、配列の参照渡し?と言うと思いますが、 この1,2,は何渡し?と言われるのでしょうか? #長い文になって申し訳ありませんが、宜しくお願い致します。

専門家に質問してみよう