Есть структура
[cсode]
typedef struct
{
LPSTR pszVersionText;
INT nVersionTextMax;
INT nVersionTextLen;
} TcVersionInfoA, *PcVersionInfoA;
[/сcode]
И есть метод из DLL в который передается эта структура
typedef int (__stdcall* TcGetVersionExA) (PcVersionInfoA VInfo);
pszVersionText это ссылка на предварительно выделенный блок памяти размером nVersionTextMax.
То есть для вызова я должен создать структуру, выделить память для pszVersionText размером nVersionTextMax и передать это все методу который заполнит эту структуру данными.
Я сделал уже рабочий вариант типа
public struct TcVersionInfoA
{
public IntPtr pszVersionText;
INT nVersionTextMax;
INT nVersionTextLen;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct TAllocatedString
{
[MarshalAs(UnmanagedType.LPStr, SizeConst=250)]
public string Str;
}
[DllImport(DLLName, EntryPoint = "cGetVersionExW@4", CallingConvention = CallingConvention.StdCall)]
private static extern int cGetVersionEx(IntPtr VInfo);
И делаю такой вызов
public VersionInfoEx GetVersionEx()
{
TcVersionInfo verInfo = new TcVersionInfo();
verInfo.pszVersionText = GetStructureBlockInHeap(new TAllocatedString());
verInfo.nVersionTextMax = 250;
IntPtr verInfoPtr = GetStructureBlockInHeap(verInfo);
int status = 0;
VersionInfoEx res = new VersionInfoEx();
try
{
status = cGetVersionEx(verInfoPtr);
verInfo = (TcVersionInfo) Marshal.PtrToStructure(verInfoPtr, verInfo.GetType());
res.pszVersionText = Marshal.PtrToStringUni(verInfo.pszVersionText);
}
finally
{
Marshal.DestroyStructure(verInfoPtr, verInfo.GetType());
Marshal.DestroyStructure(verInfo.pszVersionText, typeof(TAllocatedString));
}
return res;
}
private IntPtr GetStructureBlockInHeap(object structure)
{
if (structure == null)
return IntPtr.Zero;
int structSizeInBytes = Marshal.SizeOf(structure.GetType());
// выделить в куче буфер для нашей структуры
IntPtr structurePtr = Marshal.AllocHGlobal(structSizeInBytes);
// скопировать .NET структуру в только что выделенный unmanaged кусок памяти
Marshal.StructureToPtr(structure, structurePtr, false);
return structurePtr;
}
Все работает, но очень уж громоздко получилось.
Подскажите плиз как все это оформить проще? Может есть такие то контструкции которые облегчат этот код?