プロが教えるわが家の防犯対策術!

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を使うと、正常動作するようです。

A 回答 (2件)

Perl のリファレンスは C などのポインタじゃないよ.



Perl から C の関数を呼びたいなら... XS?

この回答への補足

ご返信ありがとうございます。

>Perl から C の関数を呼びたい
というより、dll化された関数を呼んで、その結果をperlの変数に収めたいです
XS等を使うとなると、同じコードを2箇所に書くことになりかねないので、避けたいです。
cの方でポインタを使わなければ、うまく呼べるのですが・・・
dllの関数を使う場合、配列のすべての要素を渡すしか方法は無いのでしょうか?

補足日時:2011/08/31 23:40
    • good
    • 0
この回答へのお礼

結局色々と調べて、どうやら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さん、ありがとうございました。

お礼日時:2011/09/01 01:20

Win32::API は使ったことないのですが、



http://search.cpan.org/~cosimo/Win32-API-0.64/AP …

をみると、 int の引数に対応するのは N ではなく、 I じゃないですか。

この回答への補足

ご回答ありがとうございます。
Iだと、int型
Nだと、long int型
になるようです。
Iで再度実行してみましたが、以前めちゃくちゃな値のままです。
もしかして、perl自体に、実際のメモリアドレスを得る手段は無いのでしょうか・・・?

補足日時:2011/09/01 00:12
    • good
    • 0
この回答へのお礼

ありがとうございます。解決しました。
解決に至った経緯は、私のTacosanさんへのお礼を御覧ください。

お礼日時:2011/09/01 01:21

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!