2014-12-28 3 views
2

Сервер простой ATL COM:C# как преобразовать IntPtr в структуру?

STDMETHODIMP CMyMath::get_Version(sVersionStruct **ppVer) 
{ 
    sVersionStruct* pVer = reinterpret_cast<sVersionStruct*>(CoTaskMemAlloc(sizeof(sVersionStruct))); 
    if (!pVer) { 
     return E_OUTOFMEMORY; 
    } else { 
     *pVer = ver_; 
     *ppVer = pVer; 
     return S_OK; 
    } 
    return S_OK; 
} 

STDMETHODIMP CMyMath::put_Version(sVersionStruct* ver) 
{ 
    ver_ = *ver; 
    return S_OK; 
} 

определение IDL:

typedef 
[ 
    uuid(72A4AA5B-6AD0-4249-B4CB-2FFB08301608) 
] 
struct tagVersionStruct { 
    int majorVersion; 
    int minorVersion; 
} sVersionStruct; 

    [propget] 
    HRESULT Version([out, retval, ref]sVersionStruct** ver); 
    [propput] 
    HRESULT Version([in]sVersionStruct* ver) 

C# .NET клиент:

MathServLib.sVersionStruct ver; 
    ver.minorVersion = 1; 
    ver.majorVersion = 3; 
    math.set_Version(ver); 

    ver.minorVersion = 0; 
    ver.majorVersion = 0; 
    IntPtr ptr = math.get_Version(); 
    int i = Marshal.ReadInt32(ptr); // RETURN RIGHT VALUE 3 
    Marshal.PtrToStructure(ptr, ver); 

Последняя строка возвращает исключение:

An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll. This structure is not value type. 

Так как Marshal.ReadInt32(ptr) может вернуть правильное значение 3, почему нельзя преобразовать IntPtr в структуру?

PS: sVersionStruct от ILSpy:

namespace MathServLib 
{ 
    [Guid("72A4AA5B-6AD0-4249-B4CB-2FFB08301608")] 
    [StructLayout(LayoutKind.Sequential, Pack = 4)] 
    public struct sVersionStruct 
    { 
     public int majorVersion; 
     public int minorVersion; 
    } 
} 
+1

Какое сообщение об исключении? – SLaks

+0

@SLaks: System.ArgumentException, эта структура не является типом значений. – Jichao

ответ

7

Вы должны вызвать перегрузку PtrToStructure, что ожидает тип вместо объекта. Вероятно, это вызывает ошибку:

var ver = Marshal.PtrToStructure(ptr, typeof(MathServLib.sVersionStruct)); 
+1

Существует перегрузка, которая берет объект. http://msdn.microsoft.com/en-us/library/vstudio/30ex8z62(v=vs.100).aspx –

+0

Спасибо, вы правы, я прочитал msdn, который сказал, что первая перегрузка не принимает тип значения. – Jichao

+1

@ Hamlet-Hakobyan: для типов значений (structs) вам нужна перегрузка с параметром Type. –

Смежные вопросы