0

Perl スクリプト

use Win32::API;  
use Win32::API::Callback;  

my $callback = Win32::API::Callback->new(Perl_Func,"PN", "N");  

 #Import 'C_Func' Function from dll  
my $test = Win32::API->new('dll_test','C_Func','KP','N');  
my $buf = pack('i*', (1, 2, 3));  
 #Calling the C dll Function 'C_Func' with arguments as pointer to 'Perl_Func' and integer array  
my $ret = $test->Call( $callback, $buf);  
print "final value=".$ret."\n";

「Perl_Func」の定義

sub Perl_Func
{  

        ($a,$b)=@_;  
        print "entered into Perl Function"."\n";  
        print "int variable from dll=".$b."\n";  
        print "array first element from dll=".$a[0]."\n";  **#unable to access the value**  
        $res=$a[0]+$a[1]+$a[2]; **# unable to access the values here** 
        return $res;  
}

C Dll "dll_test"

int __stdcall C_Func( int (*PerlExpFunc)( int *, int ), int *d)  
{  

        int res,c[3]; 
        c[0]=d[0]; c[1]=d[1]; c[2]=d[2];   
        res=PerlExpFunc(c,10);  
        return(res);  
}

ここで出力は次のようになります

    Perl関数に入った  
    dll=10 からの int 変数  
    dll の配列の最初の要素 =    
    最終値=0  

したがって、プログラムは dll から呼び出される 'Perl_Func' に入ります。しかし、この関数内では、dll からポインター ( cdll および$a'Perl_Func' の変数) として渡された配列の値にアクセスできません。したがって、値は表示されず$a[0]、最終値、つまり 1、2、および 3 の合計はゼロになります。Cセクションから渡されたポインターから配列への値を、Perlセクションで正しく抽出していないと思います。そのための適切な方法を教えてください。

4

1 に答える 1

1

Win32::APIWin32::API::Callbackを使用してこれを行うことができます。さらにヘルプが必要な場合は、より多くの情報を提供する必要があります。

これまでの進捗状況は次のとおりです。

mydll.c

#include <stdlib.h>
#include <windows.h>

__declspec(dllexport)
int __cdecl C_Func(LONG (*PerlExpFunc)(PLONG, LONG), PLONG c) {
    int result;
    result = PerlExpFunc(c, 10);
    return result;
}

以下を使用してコンパイル:

C:\Temp> cl mydll.c /LD /Gd /W3

test.pl

use strict; use warnings;
use Win32::API;
use Win32::API::Callback;
use YAML;

my $C_Func = Win32::API->new('mydll', 'C_Func', 'KP', 'N', '_cdecl');

my $callback = Win32::API::Callback->new(sub {
        my ($x, $y) = @_;
        print Dump \@_;
        return 42;
    }, ['P', 'N'], 'N'
);

my $array = pack 'L*', 0x41, 0x42, 0x43;

my $ret = $C_Func->Call($callback, $array);

print "final value= $ret\n";

これからの出力は次のとおりです。

---
- あ
- 10
最終値= 42

明らかに、コールバックは渡された配列の最初の要素を受け取っています。3 つの値はすべて になりC_Funcます。受信側がどうなっているのかわかりません。

アップデート:

これが問題です(からWin32-API-0.68/Callback/Callback.xs)。にはPerformCallback、次のものがあります。

for(i=0; i < nparams; i++) {
    switch(params[i].t) {
    case T_STRUCTURE:
        itoa(i, ikey, 10);
        XPUSHs(sv_2mortal(*(hv_fetch((HV*)SvRV(self), ikey, strlen(ikey), 0))));
        break;
    case T_POINTER:
        XPUSHs(sv_2mortal(newSVpv((char *) params[i].p, 0)));
        break;
    case T_INTEGER:
    case T_NUMBER:
        XPUSHs(sv_2mortal(newSViv((int) params[i].l)));
        break;
    }
}

のケースを見るとT_POINTER、配列の最初の要素だけが返されている理由は明らかです (これは、出力の 16 進ダンプを渡し0xdeadbeefて観察することで確認できます)。efbeadde

于 2012-05-02T00:55:12.880 に答える