2

我正在使用 Win32::API 调用在接受 C++ 结构指针的 DLL 中导出的任意函数。

struct PluginInfo {
        int  nStructSize;   
        int  nType;     
        int  nVersion;    
        int  nIDCode;    
        char         szName[ 64 ];  
        char            szVendor[ 64 ];
        int  nCertificate;  
        int  nMinAmiVersion;
};

因为我们需要使用“pack”函数来构造结构并且需要传递一个参数

my $name = " " x 64;
my $vendor = " " x 64;
my $pluginInfo = pack('IIIIC64C64II',0,0,0,0,$name,$vendor,0,0);

它没有正确构建结构。
似乎应用于 C 的长度参数会吞噬那些许多参数。
有人可以建议从 Perl 和 passon 到 dll 调用中构建这种结构的最佳方法。

在此先感谢
Naga Kiran

4

2 回答 2

2

在您的模板中使用Z(NUL-padded string),如

my $pluginInfo = pack('IIIIZ64Z64II',0,0,0,0,$name,$vendor,0,0);

另外,看一下Win32::API::Struct,它是 Win32::API 模块的一部分。

于 2009-12-06T19:22:20.707 回答
1

对于任何复杂的事情,请查看Convert::Binary::C。起初它可能看起来令人生畏,但一旦你意识到它的力量,它就会大开眼界。

更新:让我补充一点信息。您需要查看模块手册页的特定部分,以了解使用它的主要原因。为方便起见,我将引用它:

为什么使用 Convert::Binary::C?

假设您要根据以下 C 结构打包(或解包)数据:

struct foo {
  char ary[3];
  unsigned short baz;
  int bar;
};

你当然可以使用 Perl 的 pack 和 unpack 函数:

@ary = (1, 2, 3);
$baz = 40000;  
$bar = -4711;
$binary = pack 'c3 Si', @ary, $baz, $bar;

但这意味着结构成员是字节对齐的。如果它们是长对齐的(这是大多数编译器的默认设置),您必须编写

 $binary = pack 'c3 x S x2 i', @ary, $baz, $bar;

这并没有真正增加可读性。

现在想象一下,您需要为具有不同字节顺序的完全不同的架构打包数据。你会再次查看 pack 手册页,也许会想出这个:

$binary = pack 'c3 x n x2 N', @ary, $baz, $bar;

但是,如果您尝试再次解压缩 $foo,您的签名值会变成无符号值。

这一切仍然可以用 Perl 来管理。但是想象一下你的结构会变得更复杂吗?想象一下,您需要支持不同的平台?想象一下,您需要对结构进行更改?您不仅需要更改 C 源代码,还需要更改 Perl 代码中的几十个包字符串。这不好玩。Perl 应该很有趣。

现在,如果您可以阅读您已经编写的 C 源代码并使用其中定义的所有类型进行打包和解包,那不是很好吗?这就是 Convert::Binary::C 所做的。

于 2009-12-07T08:41:49.287 回答