Передача указателя структуры C ++ из Perl в вызов произвольной функции dll
-
13-09-2019 - |
Вопрос
Я использую Win32::API для вызова произвольной функции, экспортируемой в DLL, которая принимает указатель структуры C ++.
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 и передать вызов dll.
Заранее благодарю,
Нага Киран
Решение
Использовать Z
(строка, дополненная NUL) в вашем шаблоне, как в
my $pluginInfo = pack('IIIIZ64Z64II',0,0,0,0,$name,$vendor,0,0);
Также взгляните на Win32::API::Struct
, который является частью модуля Win32::API.
Другие советы
Если есть что-то сложное, ознакомьтесь с Конвертировать::Двоичный файл::C.Поначалу это может показаться пугающим, но как только вы осознаете его силу, это открывает глаза.
Обновить:Позвольте мне добавить немного информации.Вам нужно взглянуть на конкретный раздел справочной страницы модуля по главной причине, чтобы использовать его.Я процитирую это для удобства:
Зачем использовать Convert:: Binary::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;
Но это подразумевает, что элементы struct выровнены по байтам.Если бы они были выровнены по длине (что используется по умолчанию для большинства компиляторов), вам пришлось бы написать
$binary = pack 'c3 x S x2 i', @ary, $baz, $bar;
который на самом деле не повышают читаемость.
Теперь представьте, что вам нужно упаковать данные для совершенно другой архитектуры с другим порядком байтов .Вы бы заглянули в пакет manpage еще раз и, возможно, нашли это:
$binary = pack 'c3 x n x2 N', @ary, $baz, $bar;
Однако, если вы попытаетесь снова распаковать $foo , ваши подписанные значения превратятся в неподписанные.
Всем этим по-прежнему можно управлять с помощью Perl.Но представьте, что ваши структуры становятся более сложными?Представьте, что вам нужно поддерживать разные платформы?Представьте, вам нужно внести изменения в структуры?Вам придется не только изменить исходный код C, но и десятки упаковывать строки в вашем Perl-коде.Это совсем не весело.И Perl должен быть веселым.
Теперь, разве не было бы здорово, если бы вы могли просто прочитать в исходном коде C, который вы уже написали, и использовать все типы , определенные там для упаковки и распаковки?Это то, что делает Convert::Binary::C.