7
votes

DELPHI PCHAR À C ++ CONSTRY CHAR *

J'essaie d'utiliser une DLL C ++ à partir d'un programme natif. Je suis le scénario de méthode virtuelle comme expliqué ici

permet de dire ma signature de fonction C ++ est de la forme p> xxx pré>

et la signature Delphi correspondante est p> xxx pré>

et quelque part du programme Delphi, je peux appeler xxx pré>

Le contrôle entre dans la DLL, mais SZIP et SZPort Les paramètres formels reçoivent uniquement le premier caractère de la propriété intellectuelle et du port que j'avais passé du programme Delphi. P>

Je comprends que cela a à voir avec NULL, terminant correctement la chaîne à Delphi. Donc, j'avais essayé aussi ce qui suit. P>

var
  pzIp, pzPort: PChar;
  szIp, szPort: string; 

begin
   szIp   := '192.168.1.2';
   szPort := '9777';
   //initilize memory for pchar vars
   GetMem(pzIp, Length(szIp)+1);
   GetMem(pzPort, Length(szPort)+1);
   //null terminate the strings
   pzIp[Length(szIp)+1] := #0;
   pzPort[Length(szPort)+1] := #0;
   //copy strings to pchar
   StrPCopy(pzIp, szIp);
   StrPCopy(pzPort, szPort);
end.


0 commentaires

3 Réponses :


3
votes

Si je comprends bien, votre prototype de fonction doit également être aussi STDCALL.

function Setup(ip, port: PChar):Integer: virtual; stdcall; abstract;


3 commentaires

Hmm, ça n'a pas fonctionné. Le même résultat. Mais je pourrais me débarrasser d'un accident de violation d'accès lorsque la fonction C ++ est renvoyée. Donc, je suppose que je fais des progrès :)


Il est temps de tomber à la vue de l'assemblage :)


le faire stdcall m'avait résolu quelques autres problèmes, +1 pour la pointe



4
votes

est de la même taille dans les deux compilateurs? Si vous utilisez D2009 / D2010, Char est maintenant 16 bits.


2 commentaires

Ouais j'utilise D2010. Et mon code C ++ est 32 bits. Donc, la taille du personnage doit correspondre à droite?


Pas nécessairement: BCB4 est un compilateur C ++ 32 bits, mais un article est un octet. Vous pouvez être null-terminer votre chaîne prématurément avec le 0 High-Byte pour le premier caractère. Essayez de changer votre code de test ci-dessus pour déclarer Szip et Szport en tant qu'Anstring au lieu de la chaîne.



18
votes

dans Delphi 2010 (et Delphi 2009) Le type "Char" est en fait un widecharar - c'est-à-dire 16 bits de large. Ainsi, lorsque vous appelez votre fonction C ++, si cela s'attend à ce que cela soit de 8 bits de largeur (appelé «ANSI», plutôt que UNICODE), alors il va mal interpréter le paramètre d'entrée.

E.g. Si vous passez la chaîne 'abc' # 0 forte> (je montre le terminateur null explicitement, mais il s'agit simplement d'une partie implicite d'une chaîne à Delphi et n'a pas besoin d'être ajoutée spécifiquement) cela passe une Pointeur sur une séquence 8 octets forte>, pas strud> 4 octets! p>

mais parce que les 3 caractères de votre chaîne n'ont que des valeurs de point de code 8 bits ( En termes unicode, cela signifie que ce que le code C ++ "voit" est une chaîne qui ressemble à: p> xxx pré>

ce qui expliquerait pourquoi votre code C ++ semble seulement obtenir le premier caractère de la chaîne - c'est voir le # 0 fort> dans le 2e 2e octet fort> de ce premier caractère et en supposant qu'il s'agisse du terminateur null pour toute la chaîne. P>

Vous devez soit modifier votre code C ++ pour recevoir correctement les pointeurs sur Widecharar Strong> Strings, ou modifier la signature de fonction dans Delphi et convertir vos chaînes en Ansistring Strong> dans le code Delphi avant em> qui passe ces t o la fonction C ++: p>

signature de fonction révisée: p> xxx pré>

et la "main longue" correspondante montrant la conversion de chaînes à ansistring fort > Avant d'appeler la fonction - le compilateur peut prendre en charge cela pour vous, mais vous trouverez peut-être utile de préciser votre code plutôt que de compter sur «Compiler Magic»: P>

  var
    sIPAddress: ANSIString;
    sPort: ANSIString;
  begin   
    sIPAddress := '192.168.1.100';
    sPort      := '97777';

    pObj.Setup(sIPAddress, sPort);

    // etc... 


2 commentaires

Merci pour l'explication plus détaillée: ma réponse a été une pensée rapide qui s'est avérée juste, mais je le recommande comme la réponse à accepter.


Merci @deltics, ça a fonctionné. Un petit changement cependant, nécessaire pour être jeté pour rendre le programme Delphi compile POBJ.Setup (Pansichar (SIPADDRESS), PANSICHAR (SPORT)); Spécial merci à @ianh aussi