Это пример кода, который вызывает MarshalDirectiveException. Хорошее объяснение SafeHandle s можно найти here.Как получить GetFunctionPointerForDelegate для метода с SafeHandle или обходным путем
[SuppressUnmanagedCodeSecurity]
private delegate SafeHandle testDelegate();
[SuppressUnmanagedCodeSecurity]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static SafeHandle test(){
FileStream fs=new FileStream("a.txt", FileMode.Create);
return fs.SafeFileHandle;
}
private static void Main(){
MethodInfo methodInfo = typeof (Program).GetMethod("test", BindingFlags.Static | BindingFlags.Public);
Delegate delegateInstance = Delegate.CreateDelegate(typeof (testDelegate), methodInfo);
//System.Runtime.InteropServices.MarshalDirectiveException
//Cannot marshal 'return value': SafeHandles cannot be returned from managed to unmanaged.
IntPtr fcePtr = Marshal.GetFunctionPointerForDelegate(delegateInstance);
// alternatively for method parameter
// throws System.Runtime.InteropServices.MarshalDirectiveException
// Cannot marshal 'parameter #1': This type can only be marshaled in restricted ways."
// alternatively for HandleRef
// System.Runtime.InteropServices.MarshalDirectiveException
// Cannot marshal 'parameter #1': HandleRefs cannot be marshaled ByRef or from unmanaged to managed.
}
Проще говоря, голые ручки, полученный в междунар или IntPtr может быть утечкой, когда исключение бросков перед тем, завернутыми в соответствующий Dipose скороговорку. Когда вы возвращаете голый дескриптор в собственный код, он, как правило, собирается g, прежде чем собственный код использует дескриптор. Мне интересно узнать, как решить эту проблему с достаточной степенью безопасности. Специально возвращающаяся ручка беспокоит меня. Это просто примеры для краткости, я не работаю с файловым дескриптором в действительности. Я бы предпочел наследовать мою собственную от SafeHandle.
[DllImport("mydll")]
public static extern void naked(IntPtr nakedHandle);
private static void Main(){
IntPtr intPtr = getHandle();
naked(intPtr);
}
private static IntPtr getHandle(){
FileStream fs = new FileStream("myfile", FileMode.CreateNew);
IntPtr ha = fs.Handle;
return ha;
// at this point, fs is garbage collected.
// ha is pointing to nonexistent or different object.
}
Что такое intPtr в getHandle()? Я не вижу, где это определено. – SwDevMan81
Я думаю, что могу помочь, но мне нужна дополнительная информация. Вы хотите иметь возможность вызвать управляемую функцию из неуправляемого кода, который принимает дескриптор в качестве первого аргумента, правильно? Передает ли этот вызов право собственности на дескриптор на управляемый код? –
@ SwDevMan81, вы правы, это была опечатка –