Передача указателя структуры C ++ из Perl в вызов произвольной функции dll

StackOverflow https://stackoverflow.com/questions/1856061

Вопрос

Я использую 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top