Espérons que vous avez déjà du code dans votre application pour éliminer correctement hors de tous les enregistrements alloués dynamiquement que vous New()
dans FillStructureForDLL()
. Je considère ce code très douteux, mais supposons qu'il s'agit d'un code réduit pour démontrer le problème seulement. Quoi qu'il en soit, la DLL à laquelle vous passez l'instance d'enregistrement ne se soucie pas de la taille du morceau de mémoire, elle ne recevra qu'un pointeur de toute façon.Donc, vous êtes libre d'augmenter la taille du dossier pour faire place à la chaîne Pascal qui est maintenant une instance temporaire sur la pile dans la version Unicode:
type
PStructureForSomeCDLL = ^TStructureForSomeCDLL;
TStructureForSomeCDLL = record
pName: PAnsiChar;
// ... other parts of the record
pNameBuffer: string;
end;
Et la fonction:
function FillStructureForDLL: PStructureForSomeDLL;
begin
New(Result);
// there may be a bug here, can't test on the Mac... idea should be clear
Result.pNameBuffer := Utf8ToAnsi(UTF8Encode(SomeObject.SomeString));
Result.pName := Result.pNameBuffer;
end;
BTW: Vous n'auriez même pas ce problème si l'enregistrement passé à la DLL était une variable de pile dans la procédure ou la fonction qui appelle la fonction DLL. Dans ce cas, les tampons de chaîne temporaires ne seront nécessaires dans la version Unicode que si plus d'un PAnsiChar
doit être passé (les appels de conversion réutiliseraient sinon la chaîne temporaire). Envisagez de changer le code en conséquence.
Edit:
Vous écrivez dans un commentaire:
Ce serait la meilleure solution si la modification des structures de DLL sont une option. Êtes-vous sûr de ne pas pouvoir utiliser cette solution?
Etes-vous sûr de ne pas pouvoir utiliser cette solution? Le point est que du POV de la DLL la structure n'est pas du tout modifiée. Peut-être que je ne me suis pas fait clair, mais la DLL ne sera pas si une structure passée à elle est exactement ce que c'est déclaré être. Il sera passé un pointeur vers la structure, et ce pointeur doit pointer vers un bloc de mémoire au moins aussi grand que la structure, et doit avoir la même disposition de la mémoire. Cependant, il peut s'agir d'un bloc de mémoire plus grand que par rapport à la structure d'origine et contenant des données supplémentaires.
Ceci est effectivement utilisé dans beaucoup d'endroits dans l'API Windows. Avez-vous déjà demandé pourquoi il y a des structures dans l'API Windows qui contiennent en premier lieu une valeur ordinale donnant la taille de la structure? C'est la clé de l'évolution de l'API tout en préservant la rétrocompatibilité. Chaque fois que de nouvelles informations sont nécessaires pour que la fonction API fonctionne, il suffit d'ajouter à la structure existante et de déclarer une nouvelle version de la structure. Notez que la disposition de la mémoire des anciennes versions de la structure est conservée. Les anciens clients de la DLL peuvent toujours appeler la nouvelle fonction, qui utilisera le membre size de la structure pour déterminer la version de l'API appelée.
Dans votre cas, il n'existe aucune version différente de la structure en ce qui concerne la DLL. Cependant, vous êtes libre de déclarer qu'il est plus grand pour votre application qu'il ne l'est réellement, à condition que la disposition de la mémoire de la structure réelle soit préservée et que des données supplémentaires ne soient ajoutées que pour . Le seul cas où cela ne fonctionnerait pas est quand la dernière partie de la structure était un enregistrement avec une taille variable, un peu comme la structure de Windows BITMAP
- un en-tête fixe et des données dynamiques. Cependant, votre enregistrement semble avoir une longueur fixe.
Bonne POV. Merci! –