Eug*_* C. 3 c++ perl winapi types
我正在尝试使用Perl的Win32 :: API模块来使用Win32 API函数DsGetSiteName().根据Windows SDK,DsGetSiteName的函数原型是:
DWORD DsGetSiteName(LPCTSTR ComputerName, LPTSTR *SiteName)
Run Code Online (Sandbox Code Playgroud)
我成功地使用这个API写了一个小的C++函数,以便更好地理解它实际上是如何工作的(我自己学习C++,但我离题了).
无论如何,根据我对API文档的理解,第二个参数应该是指向接收指向字符串的指针的变量的指针.在我的C++代码中,我写道:
LPSTR site;
LPTSTR *psite = &site;
Run Code Online (Sandbox Code Playgroud)
并使用psite指针成功调用了API.
现在我的问题是,有没有办法使用Perl的Win32 :: API做同样的事情?我尝试了以下Perl代码:
my $site = " " x 256;
my $computer = "devwin7";
my $DsFunc = Win32::API->new("netapi32","DWORD DsGetSiteNameA(LPCTSTR computer, LPTSTR site)");
my $DsResult = $DsFunc->Call($computer, $site);
print $site;
Run Code Online (Sandbox Code Playgroud)
$ DsResult中的调用结果为零(意味着成功),但$ site中的数据不是我想要的,它看起来是ASCII和不可打印字符的混合.
$ site变量可以保存分配的字符串的指针地址吗?如果是这样,有没有办法使用Win32 :: API取消引用该地址以获取字符串?
提前致谢.
Win32 :: API无法处理char**.你需要自己提取字符串.
use strict;
use warnings;
use feature qw( say state );
use Encode qw( encode decode );
use Win32::API qw( );
use constant {
NO_ERROR => 0,
ERROR_NO_SITENAME => 1919,
ERROR_NOT_ENOUGH_MEMORY => 8,
};
use constant PTR_SIZE => $Config{ptrsize};
use constant PTR_FORMAT =>
PTR_SIZE == 8 ? 'Q'
: PTR_SIZE == 4 ? 'L'
: die("Unrecognized ptrsize\n");
use constant PTR_WIN32API_TYPE =>
PTR_SIZE == 8 ? 'Q'
: PTR_SIZE == 4 ? 'N'
: die("Unrecognized ptrsize\n");
# Inefficient. Needs a C implementation.
sub decode_LPCWSTR {
my ($ptr) = @_;
return undef if !$ptr;
my $sW = '';
for (;;) {
my $chW = unpack('P2', pack(PTR_FORMAT, $ptr));
last if $chW eq "\0\0";
$sW .= $chW;
$ptr += 2;
}
return decode('UTF-16le', $sW);
}
sub NetApiBufferFree {
my ($Buffer) = @_;
state $NetApiBufferFree = Win32::API->new('netapi32.dll', 'NetApiBufferFree', PTR_WIN32API_TYPE, 'N')
or die($^E);
$NetApiBufferFree->Call($Buffer);
}
sub DsGetSiteName {
my ($ComputerName) = @_;
state $DsGetSiteName = Win32::API->new('netapi32.dll', 'DsGetSiteNameW', 'PP', 'N')
or die($^E);
my $packed_ComputerName = encode('UTF-16le', $ComputerName."\0");
my $packed_SiteName_buf_ptr = pack(PTR_FORMAT, 0);
$^E = $DsGetSiteName->Call($packed_ComputerName, $packed_SiteName_buf_ptr)
and return undef;
my $SiteName_buf_ptr = unpack(PTR_FORMAT, $packed_SiteName_buf_ptr);
my $SiteName = decode_LPCWSTR($SiteName_buf_ptr);
NetApiBufferFree($SiteName_buf_ptr);
return $SiteName;
}
{
my $computer_name = 'devwin7';
my ($site_name) = DsGetSiteName($computer_name)
or die("DsGetSiteName: $^E\n");
say $site_name;
}
Run Code Online (Sandbox Code Playgroud)
所有这些decode_LPCWSTR都是未经测试的.
我使用WIDE接口而不是ANSI接口.使用ANSI接口是不必要的限制.
PS - 我编写了John Zwinck链接的代码.
| 归档时间: |
|
| 查看次数: |
1212 次 |
| 最近记录: |