C#如何将IntPtr转换为结构体?

9
一个简单的ATL COM服务器:
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:来自ILSpy的sVersionStruct:

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

1
异常信息是什么? - SLaks
@SLaks:System.ArgumentException,这个结构体不是值类型。 - Jichao
1个回答

16
你应该调用期望类型而不是对象的PtrToStructure重载。这可能是导致错误的原因:
var ver = Marshal.PtrToStructure(ptr, typeof(MathServLib.sVersionStruct)); 

1
有一个重载函数可以接受对象参数。http://msdn.microsoft.com/zh-cn/library/vstudio/30ex8z62(v=vs.100).aspx - Hamlet Hakobyan
谢谢,你说得对,我读了 MSDN,它说第一个重载不接受值类型。 - Jichao
1
@Hamlet-Hakobyan:对于值类型(结构体),您需要使用带有Type参数的重载。 - John
2
这个答案将返回一个对象,你需要进行强制类型转换。但是你可以通过泛型避免强制类型转换:var ver = Marshal.PtrToStructure<MathServLib.sVersionStruct>(ptr); - Daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接