En utilisant Microsoft Visual C# 2010, j'ai récemment remarqué que vous pouvez passer des objets par ref au code non managé. Je me suis donc chargé de tenter d'écrire du code non managé qui convertit un char * C++ en une chaîne C# en utilisant un rappel au code managé. J'ai fait deux tentatives.Quel est le niveau de sécurité de ref lorsqu'il est utilisé avec un code dangereux?
Tentative 1: Appelez la fonction non managée qui stocke un paramètre ref. Ensuite, une fois cette fonction renvoyée au code managé, appelez une autre fonction non managée qui appelle une fonction de rappel qui convertit le caractère * en une chaîne managée.
C++
typedef void (_stdcall* CallbackFunc)(void* ManagedString, char* UnmanagedString);
CallbackFunc UnmanagedToManaged = 0;
void* ManagedString = 0;
extern "C" __declspec(dllexport) void __stdcall StoreCallback(CallbackFunc X) {
UnmanagedToManaged = X;
}
extern "C" __declspec(dllexport) void __stdcall StoreManagedStringRef(void* X) {
ManagedString = X;
}
extern "C" __declspec(dllexport) void __stdcall CallCallback() {
UnmanagedToManaged(ManagedString, "This is an unmanaged string produced by unmanaged code");
}
C#
[DllImport("Name.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void StoreCallback(CallbackFunc X);
[DllImport("Name.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void StoreManagedStringRef(ref string X);
[DllImport("Name.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void CallCallback();
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void CallbackFunc(ref string Managed, IntPtr Native);
static void Main(string[] args) {
string a = "This string should be replaced";
StoreCallback(UnmanagedToManaged);
StoreManagedStringRef(ref a);
CallCallback();
}
static void UnmanagedToManaged(ref string Managed, IntPtr Unmanaged) {
Managed = Marshal.PtrToStringAnsi(Unmanaged);
}
Tentative 2: ref chaîne passe à la fonction non géré qui passe l'arbitre de chaîne à la fonction de rappel géré.
C++
typedef void (_stdcall* CallbackFunc)(void* ManagedString, char* UnmanagedString);
CallbackFunc UnmanagedToManaged = 0;
extern "C" __declspec(dllexport) void __stdcall StoreCallback(CallbackFunc X) {
UnmanagedToManaged = X;
}
extern "C" __declspec(dllexport) void __stdcall DoEverything(void* X) {
UnmanagedToManaged(X, "This is an unmanaged string produced by unmanaged code");
}
C#
[DllImport("Name.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void StoreCallback(CallbackFunc X);
[DllImport("Name.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void DoEverything(ref string X);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void CallbackFunc(ref string Managed, IntPtr Unmanaged);
static void Main(string[] args) {
string a = "This string should be replaced";
StoreCallback(UnmanagedToManaged);
DoEverything(ref a);
}
static void UnmanagedToManaged(ref string Managed, IntPtr Unmanaged) {
Managed = Marshal.PtrToStringAnsi(Unmanaged);
}
La tentative 1 ne fonctionne pas mais la tentative 2 le fait. Dans la tentative 1, il semble que dès que le code non géré revient après avoir stocké le ref, l'arbitre devient invalide. Pourquoi cela arrive-t-il? Compte tenu des résultats de la tentative 1, j'ai des doutes que la tentative 2 fonctionnera de manière fiable. Donc, quelle est la sécurité de ref sur le côté non géré du code lorsqu'il est utilisé avec du code non managé? Ou en d'autres termes, ce qui ne fonctionnera pas dans le code non géré lors de l'utilisation ref?
choses que je voudrais savoir sont sont:
Qu'est-ce qui se passe exactement quand les objets sont passés en utilisant ref au code non managé? Est-ce que cela garantit que les objets resteront à leur position actuelle en mémoire pendant que le ref est utilisé en code non managé?
Quelles sont les limitations de ref (que ne puis-je pas faire avec un ref) en code non managé?
Le code dangereux est appelé "dangereux" pour une raison ... il est dangereux. :) – Almo