Требуют ли ref-параметры специальной обработки при собственном маршалинге, сгенерированном исходным кодом?C#

Место общения программистов C#
Ответить
Anonymous
 Требуют ли ref-параметры специальной обработки при собственном маршалинге, сгенерированном исходным кодом?

Сообщение Anonymous »

Я экспериментировал с этой новой функцией и решил использовать SymGetModuleInfo64 из dbghelp.dll в качестве примера. Я написал собственный маршаллер и могу его запустить (ниже приведен сгенерированный код), но он выдает исключение AccessViolationException, когда результат ConvertToManaged присваивается обратно ссылке. Нужен ли параметр ref специальной обработки? В настоящее время я просто создаю экземпляр IMAGEHELP_MODULE64 и устанавливаю его SizeOfStruct перед передачей его в SymGetModuleInfo64.
public unsafe partial class Test
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Interop.LibraryImportGenerator", "7.0.10.26716")]
[System.Runtime.CompilerServices.SkipLocalsInitAttribute]
private static partial bool SymGetModuleInfo64(nint hProcess, long ModuleBase64, ref global::Test.Test.IMAGEHELP_MODULE64 imgHelpModule)
{
int __lastError;
global::Test.Test.IMAGEHELP_MODULE64_Marshaller.Unmanaged __imgHelpModule_native;
bool __retVal;
int __retVal_native;
// Marshal - Convert managed data to native data.
__imgHelpModule_native = global::Test.Test.IMAGEHELP_MODULE64_Marshaller.ConvertToUnmanaged(imgHelpModule);
{
System.Runtime.InteropServices.Marshal.SetLastSystemError(0);
__retVal_native = __PInvoke(hProcess, ModuleBase64, &__imgHelpModule_native);
__lastError = System.Runtime.InteropServices.Marshal.GetLastSystemError();
}

// Unmarshal - Convert native data to managed data.
__retVal = __retVal_native != 0;
-----> imgHelpModule = global::Test.Test.IMAGEHELP_MODULE64_Marshaller.ConvertToManaged(__imgHelpModule_native);
System.Runtime.InteropServices.Marshal.SetLastPInvokeError(__lastError);
return __retVal;
// Local P/Invoke
[System.Runtime.InteropServices.DllImportAttribute("dbghelp.dll", EntryPoint = "SymGetModuleInfo64", ExactSpelling = true)]
static extern unsafe int __PInvoke(nint hProcess, long ModuleBase64, global::Test.Test.IMAGEHELP_MODULE64_Marshaller.Unmanaged* imgHelpModule);
}
}

Я пытался выделить память для параметра, чтобы убедиться, что он принадлежит мне, но что бы я ни делал, я все равно получаю исключение AccessViolationException.
Вот как выглядит класс Test, который сгенерировал приведенный выше код (ПРИМЕЧАНИЕ: меня интересовал только LoadedPdbName, поэтому я не реализовал маршалинг для всей структуры, но это не должно иметь значения , PINvoke вызов успешен):
public unsafe partial class Test
{
[StructLayout(LayoutKind.Sequential)]
[NativeMarshalling(typeof(IMAGEHELP_MODULE64_Marshaller))]
private struct IMAGEHELP_MODULE64
{
public int SizeOfStruct;
public long BaseOfImage;
public int ImageSize;
public int TimeDateStamp;
public int CheckSum;
public int NumSyms;
public SymType SymType;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string ModuleName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string ImageName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string LoadedImageName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string LoadedPdbName;

public int CVSig;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 780)]
public string CVData;

public int PdbSig;
public GUID PdbSig70;
public int PdbAge;
public bool PdbUnmatched;
public bool DbgUnmatched;
public bool LineNumbers;
public bool GlobalSymbols;
public bool TypeInfo;
public bool SourceIndexed;
public bool Publics;
public int MachineType;
public int Reserved;
}

[StructLayout(LayoutKind.Sequential)]
private struct GUID
{
public int Data1;
public ushort Data2;
public ushort Data3;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] data4;
}

[Flags]
private enum SymType : uint
{
SymNone,
SymCoff,
SymCv,
SymPdb,
SymExport,
SymDeferred,
SymSym,
SymDia,
SymVirtual,
}

[CustomMarshaller(typeof(IMAGEHELP_MODULE64), MarshalMode.Default, typeof(IMAGEHELP_MODULE64_Marshaller))]
private static unsafe class IMAGEHELP_MODULE64_Marshaller
{
[StructLayout(LayoutKind.Explicit)]
public ref struct Unmanaged
{
[FieldOffset(0)] public int SizeOfStruct;
[FieldOffset(580)] public fixed byte LoadedPdbName[256];
}

public static Unmanaged ConvertToUnmanaged(IMAGEHELP_MODULE64 managed)
{
return new Unmanaged
{
SizeOfStruct = managed.SizeOfStruct
};
}

public static IMAGEHELP_MODULE64 ConvertToManaged(Unmanaged unmanaged)
{
return new IMAGEHELP_MODULE64
{
LoadedPdbName = AnsiStringMarshaller.ConvertToManaged(unmanaged.LoadedPdbName)
};
}
}

[LibraryImport("dbghelp.dll", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool SymGetModuleInfo64(nint hProcess, long ModuleBase64,
ref IMAGEHELP_MODULE64 imgHelpModule);
}

И вот как он используется:
var moduleInfo = new IMAGEHELP_MODULE64();
moduleInfo.SizeOfStruct = Marshal.SizeOf(moduleInfo);
if (!SymGetModuleInfo64(_processPtr, _baseOfDll, ref moduleInfo))
throw new Win32Exception(Marshal.GetLastWin32Error());


Подробнее здесь: https://stackoverflow.com/questions/792 ... marshaling
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»