Comment puis-je passer un tampon de chaîne vide qui peut être écrit de natif à c #?

J’essaie d’extraire une chaîne de mon code géré dans mon code non géré:

dll non gérée:

typedef int (__stdcall * GetNameFromDictionaryCallback)(ULONGLONG id, WCHAR * name); declspec(dllexport) void __stdcall UnmanagedSetNameLookupCallback(GetNameFromDictionaryCallback fn) { GetNameFromDictionaryCallback GetNameFromDictionary = fn; WCHAR * value = new WCHAR[256]; ULONGLONG key = 0x250000000DA44785; GetNameFromDictionary(key, value); // reverse P/Invoke call to C# function wprintf_s("%ls", value); // just to display the result for simplicity delete value; } 

dll gérée:

 public class ProgramInterop { private delegate int GetNameFromDictionaryCallback(UInt64 key, ssortingng value); private static GetNameFromDictionaryCallback mGetNameInstance; private Dictionary dict; private ProgramInterop() { mGetNameInstance = new GetNameFromDictionaryCallback(GetNameFromDictionary); UnmanagedSetNameLookupCallback(mGetNameInstance); } public bool GetNameFromDictionary(UInt64 key, ssortingng value) { return dict.TryGetValue(key, out value); } [DllImport("Unmanaged.dll")] private static extern void UnmanagedSetNameLookupCallback(GetNameFromDictionaryCallback fn); } 

Au sein de mon programme géré, ma chaîne a l’air d’être correcte, mais elle se transforme en ordures du côté non géré. Je n’ai pas copié tout le code mais je pense que cela explique ce que j’essaie d’accomplir. Si je m’y prends mal ou si j’ai commis des erreurs, merci de me le faire savoir. Merci.

Essaye ça:

 delegate int GetNameFromDictionaryCallback( UInt64 key, [MarshalAs(UnmanagedType.LPWStr)] SsortingngBuilder value); public bool GetNameFromDictionary(UInt64 key, SsortingngBuilder value) { ssortingng s; if (dict.TryGetValue(key, out s)) { value.Append(s); return true; } return false; } 

J’ai rencontré ce problème en essayant de renvoyer une chaîne de C # à C. J’ai rencontré beaucoup d’impasses, mais Olivier Levrey, sur codeproject, a suggéré l’utilisation de IntPtr pour accomplir cela. La solution a très bien fonctionné pour moi.

Actuellement, vous avez cette déclaration de délégué:

 private delegate int GetNameFromDictionaryCallback(UInt64 key, ssortingng value); 

Ce qui me vient immédiatement à l’esprit, c’est qu’en réalité, la value doit être un paramètre out , comme pour IDictionary<,>.TryGetValue(key, out value) . Pour qu’elle soit déclarée nue en tant que ssortingng value elle ne fournit aucune occasion sémantique de renvoyer la valeur réelle ! Comme @dtb le suggère, une option souvent offerte consiste à utiliser un constructeur de SsortingngBuilder . Pour moi, j’ai exactement le résultat que vous avez obtenu – la chaîne renvoyée du côté C était gobbledygook. Mais la solution d’Olivier a fonctionné.

Modifiez votre délégué pour utiliser un IntPtr comme value :

 private delegate int GetNameFromDictionaryCallback(UInt64 key, IntPtr value); 

value représente une chaîne non gérée à laquelle nous pouvons affecter une valeur. Les étapes à suivre pour y parvenir sont un peu un fouillis, mais cela fonctionne à la fin.

En supposant que vous ayez des chaînes que vous souhaitez retourner au côté C, il s’agit du code que vous devez implémenter pour transporter son contenu dans la value IntPtr :

 // Convert from managed to unmanaged ssortingng and store in `sPtr` IntPtr sPtr = Marshal.SsortingngToHGlobalAnsi(s); // Create a byte array to receive the bytes of the unmanaged ssortingng (including null terminator) var sBytes = new byte[s.Length + 1]; // Copy the the bytes in the unmanaged ssortingng into the byte array Marshal.Copy(sPtr, sBytes, 0, s.Length); // Copy the bytes from the byte array into the buffer Marshal.Copy(sBytes, 0, buffer, sBytes.Length); // Free the unmanaged ssortingng Marshal.FreeHGlobal(sPtr); 

Une fois cela fait, votre valeur de retour a été copiée dans la mémoire tampon nommée par value .