Passe pointeur de structure C ++ de Perl arbitraire appel de fonction dll
-
13-09-2019 - |
Question
J'utilise Win32 :: API pour appeler une fonction exportée dans une arbitraire DLL qui accepte un pointeur de structure C ++.
struct PluginInfo {
int nStructSize;
int nType;
int nVersion;
int nIDCode;
char szName[ 64 ];
char szVendor[ 64 ];
int nCertificate;
int nMinAmiVersion;
};
Comme nous avons besoin d'utiliser la fonction « pack » pour construire la structure et la nécessité de passer un argument
my $name = " " x 64;
my $vendor = " " x 64;
my $pluginInfo = pack('IIIIC64C64II',0,0,0,0,$name,$vendor,0,0);
Ce ne est pas la construction de la structure correctement.
Il semble que l'argument de longueur appliquée à C gobe ces nombreux arguments.
Quelqu'un peut s'il vous plaît suggérer la meilleure façon de construire cette structure forme Perl et passon à l'appel dll.
Merci à l'avance,
Naga Kiran
La solution
Utilisez Z
(string NUL rembourré) dans votre modèle, comme dans
my $pluginInfo = pack('IIIIZ64Z64II',0,0,0,0,$name,$vendor,0,0);
De plus, jetez un oeil à Win32::API::Struct
, qui fait partie du module API Win32.
Autres conseils
Pour tout compliqué, consultez Convert :: Binary :: C . Il peut sembler intimidant au début, mais une fois que vous vous rendez compte de son pouvoir, il est ouvert les yeux.
Mise à jour: Permettez-moi d'ajouter un peu d'information. Vous devez avoir un coup d'oeil à section spécifique manpage du module pour la raison principale de l'utiliser. Je vais le citer pour des raisons pratiques:
Pourquoi utiliser Convert :: Binary :: C?
Dites que vous voulez emballer (ou déballer) données en fonction du C suivant structure:
struct foo {
char ary[3];
unsigned short baz;
int bar;
};
Vous pouvez bien sûr utiliser le pack Perl et déballer les fonctions:
@ary = (1, 2, 3);
$baz = 40000;
$bar = -4711;
$binary = pack 'c3 Si', @ary, $baz, $bar;
Mais cela implique que la struct sont alignés octet membres. Si elles étaient longue alignés (qui est la valeur par défaut pour la plupart des compilateurs), vous devriez écrire
$binary = pack 'c3 x S x2 i', @ary, $baz, $bar;
qui n'augmente pas vraiment lisibilité.
Maintenant, imaginez que vous devez emballer le données pour un tout autre l'architecture avec différents octets ordre. Vous regardez dans le pack et peut-être à nouveau manpage venir avec ceci:
$binary = pack 'c3 x n x2 N', @ary, $baz, $bar;
Cependant, si vous essayez de déballer $ foo encore une fois, vos valeurs signées ont tourné dans les non signés.
Tout cela peut encore être géré avec Perl. Mais imaginez vos structures se plus complexe? Imaginez que vous devez soutenir différentes plates-formes? Imaginer vous devez apporter des modifications à la structures? Vous aurez non seulement à changer la source de C mais aussi des dizaines de chaînes de paquet dans votre code Perl. Cette est pas amusant. Et Perl devrait être amusant.
Maintenant, ça ne serait pas génial si vous pouviez juste de lire dans la source de C que vous avez déjà écrit et utiliser tous les types il défini pour l'emballage et déballage? C'est ce que Convert :: Binary :: C fait.