通过p/invoke修改结构布局 [英] Modify struct layout from p/invoke

查看:89
本文介绍了通过p/invoke修改结构布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找有关更改返回/传递给p/invoke函数的对象的结构/类布局的最佳实践指导.我一直在寻找答案,但也许我太累了,没有有效地进行搜索.

I'm looking for best practice guidance around changing the struct/class layout of objects returned/passed into a p/invoke function. I've searched for an answer to this but maybe I'm just too tired and I'm not searching effectively.

我能想到的最简单的例子(实际例子在这里有点太复杂)是类似 GetWindowRect .

The simplest example I can come up with (the real one is a bit too complex for here) is with something like GetWindowRect.

如果我想向RECT结构添加一些额外的属性,我应该只是将其添加到结构本身的定义中,还是应该切换到子类以添加额外的属性?

If I wanted to add a few extra properties to the RECT struct, should I just add it to the definition for the struct itself or should I switch over to subclassing to add the extra properties?

是否存在Microsoft或其他可靠来源关于以下方法的最佳实践?两者都违反了最佳实践吗?

Is there a best practice from Microsoft or another reliable source around the following methods? Are both of these against best practice?

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int Left;        // x position of upper-left corner
    public int Top;         // y position of upper-left corner
    public int Right;       // x position of lower-right corner
    public int Bottom;      // y position of lower-right corner

    public string Extra;    // ADDED
}

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);

[StructLayout(LayoutKind.Sequential)]
public class RECT
{
    public int Left;        // x position of upper-left corner
    public int Top;         // y position of upper-left corner
    public int Right;       // x position of lower-right corner
    public int Bottom;      // y position of lower-right corner
}

public class RectEx : RECT
{
    public string Extra;    // Added

    public RectEx(RECT r)
    {
        Left = r.Left;
        Top = r.Top;
        Right = r.Right;
        Bottom = r.Bottom;
        Extra = "test";
    }
}

推荐答案

这里是另一个选择:这使您可以维护本机功能,并为正在使用的对象提供一定的安全性.

Here is another option: this allows you to maintain native functionality and provides some safety over the objects you are using.

// used internally in native method
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
    public int Left;        // x position of upper-left corner
    public int Top;         // y position of upper-left corner
    public int Right;       // x position of lower-right corner
    public int Bottom;      // y position of lower-right corner
}


// public accessible struct with extra fields 
public struct RectEx
{
    public int Left;        // x position of upper-left corner
    public int Top;         // y position of upper-left corner
    public int Right;       // x position of lower-right corner
    public int Bottom;      // y position of lower-right corner

    public dynamic Extra = "Extra";
}


public static class UnsafeNativeMethods
{
    //used internally to populate RECT struct
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);

    //public safe method with exception handling and returns a RectEx
    public static RectEx GetWindowRectangle(HandleRef hWnd)
    {
        RECT r = new RECT();
        RectEx result = new RectEx();

        try
        {
            GetWindowRect(hWnd, r);
            result.Left = r.Left;
            result.Top = r.Top;
            result.Right = r.Right;
            result.Bottom = r.Bottom;
            // assign extra fields
        }
        catch(Exception ex)
        {
            // handle ex
        }

    return result;
    }
}

这篇关于通过p/invoke修改结构布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆