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 作为指针传递的数组中的值(c在 dll 和$a'Perl_Func' 中的变量)。因此,没有显示任何值$a[0],最终值(即 1,2 和 3 的总和)为零。我想我没有在 Perl 部分正确地从 C 部分传递的指向数组的指针中提取值。请告诉我这样做的正确方法。

4

1 回答 1

1

您可以使用Win32::APIWin32::API::Callback来做到这一点。如需更多帮助,您将需要提供更多信息。

以下是目前的进展:

我的dll.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

测试.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

显然,回调正在接收传递给它的数组的第一个元素。所有三个值都使它成为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,很清楚为什么我们只返回数组的第一个元素(您可以通过在输出的十六进制转储中传递0xdeadbeef和观察来验证这一点)。efbeadde

于 2012-05-02T00:55:12.880 回答