Передача указателя структуры C ++ из Perl в произвольный вызов функции dll - PullRequest
2 голосов
/ 06 декабря 2009

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

Заранее спасибо,
Нага Киран

Ответы [ 2 ]

2 голосов
/ 06 декабря 2009

Используйте Z (NUL-дополненную строку) в вашем шаблоне, как в

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

Также посмотрите на Win32::API::Struct, который является частью модуля Win32 :: API.

1 голос
/ 07 декабря 2009

Для чего-либо сложного, проверьте Convert :: Binary :: C . Сначала это может показаться пугающим, но как только вы осознаете его силу, это откровение.

Обновление: позвольте мне добавить немного информации. Вам нужно взглянуть на специфический раздел справочной страницы модуля по основной причине его использования. Я приведу это для удобства:

Зачем использовать Convert :: Binary :: C?

Скажем, вы хотите упаковать (или распаковать) данные в соответствии со следующим C структура:

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

Конечно, вы можете использовать пакет Perl и распаковать функции:

@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;

который на самом деле не увеличивается читаемость.

Теперь представьте, что вам нужно упаковать данные для совершенно другого архитектура с другим байтом порядок. Вы бы заглянули в стаю manpage снова и, возможно, придумать это:

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

Однако, если вы попытаетесь распаковать $ foo опять ваши подписанные значения превратились на неподписанные.

Всем этим еще можно управлять с помощью Perl. Но представьте, что ваши структуры получают более сложный? Представь, что тебе нужно поддерживать разные платформы? Представить вам нужно внести изменения в структуры? Вам придется не только изменить источник C, но также десятки упакуйте строки в свой код Perl. это это не весело. И Perl должен быть веселым.

Теперь, разве не было бы замечательно, если бы вы могли просто прочитайте в источнике C вы уже написано и использовать все типы определено там для упаковки и распаковка? Это то что Convert :: Binary :: C делает.

...