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";
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;
}
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);
}
所以这里输出看起来像这样
entered into Perl Function int variable from dll=10 array first element from dll= final value=0
因此程序正在进入从dll调用的'Perl_Func'。但是在这个函数中,它无法访问作为指针传递的数组中的值(dll中的变量c
和'Perl_Func'中的$a
)。因此,$a[0]
和最终值没有显示任何值,即1,2和3的总和出现为零。 我想我没有从指针到数组中提取值,从C部分传递,正确地在Perl部分中传递。请告诉我正确的方法。
答案 0 :(得分:1)
您可以使用Win32::API和Win32::API::Callback执行此操作。如需更多帮助,您需要提供更多信息。
目前为止的进展如下:
#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
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";
这个输出是:
--- - A - 10 final value= 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
来验证输出的十六进制转储。)