※ ChatGPTを利用し、要約された質問です(原文:perlで配列のポインタをdllに渡すには?)
perlで配列のポインタをdllに渡すには?
このQ&Aのポイント
perlで配列のポインタをdllに渡す方法が分からない。C言語側でdllをビルドし、配列の先頭要素へのポインタと要素数を渡すと要素の平均を整数で返す関数を作成したが、正常な出力値が得られない。
現在使っているのはActive Perlの最新版(x86)。他のプログラムからこのdllを使うと正常に動作することが確認されている。
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では実メモリのアドレスを得ることは不可能らしいという結論に辿り着きました。 幸い、渡そうとしている配列は一桁の整数の配列なので、C側で //数字の文字列へのポインタを渡すと、各文字の平均を整数で返す関数 int avr(const char *array,int kazu) { int value=0; for(int i=0;i<kazu;i++) { value+=array[i]-48; /* ASCII文字の数字から普通の数字へ変換 */ } return value/kazu; } として、perlで use Win32::API; my $function = Win32::API->new("avr", "avr", "PN", "N"); @array=(1,2,3,4,5); #配列から渡すべき文字列を作る my $str=""; foreach (@array) { chomp $_; #この場合は要らないが、ファイルから読み込んだ配列等の場合は必要 $str.=$_; } $avr=$function->Call($str,5); #avr('12345',5); print "Content-type: text/html\n\n"; print $avr; などとしてみたところ、正常に動きました。 根本的な解決ではないのですが、これで解決と致します。 Tacosanさんのおかげで、「perlでは実メモリのアドレスを得ることは不可能」ということに気がついたので、ベストアンサーに致します。 Tacosanさん、t-okuraさん、ありがとうございました。
補足
ご返信ありがとうございます。 >Perl から C の関数を呼びたい というより、dll化された関数を呼んで、その結果をperlの変数に収めたいです XS等を使うとなると、同じコードを2箇所に書くことになりかねないので、避けたいです。 cの方でポインタを使わなければ、うまく呼べるのですが・・・ dllの関数を使う場合、配列のすべての要素を渡すしか方法は無いのでしょうか?