首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在压缩框架中是否有StructLayout“包”属性的替代方案?

在压缩框架中是否有StructLayout“包”属性的替代方案?
EN

Stack Overflow用户
提问于 2009-07-14 11:54:02
回答 7查看 8.2K关注 0票数 6

我想做以下几件事:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  public struct SomeStruct
  {
     public byte  SomeByte;
     public int   SomeInt;
     public short SomeShort;
     public byte  SomeByte2;
  }

既然紧凑框架中不支持Pack,那么有没有替代方案?

更新:显式设置结构并为每个对象提供FieldOffset也不起作用,因为这不会影响结构的打包方式

Update2:如果您尝试以下操作,CF程序甚至不会运行,因为它的结构是如何打包的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[StructLayout(LayoutKind.Explicit, Size=8)]
public struct SomeStruct
{
   [FieldOffset(0)]
   public byte SomeByte;
   [FieldOffset(1)]
   public int SomeInt;
   [FieldOffset(5)]
   public short SomeShort;
   [FieldOffset(7)]
   public byte SomeByte2;
}

我知道这看起来很难相信,但如果你试一试,你就会明白。将其添加到CF项目中并尝试运行它,您将获得一个TypeLoadException。将偏移量分别更改为0、4、8、10,它将起作用(但大小最终为12)。

我希望也许有人有一个使用反射的解决方案,也许可以分别封送每个字段类型的大小(涉及到递归来处理结构或类型数组中的结构)。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-08-27 06:12:53

这可能不是你想要的答案,但无论如何我都会把它贴出来:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public struct SomeStruct
{
    public byte SomeByte;
    public int SomeInt;
    public short SomeShort;
    public byte SomeByte2;


    public byte[] APIStruct
    {
        get
        {
            byte[] output = new byte[8];
            output[0] = this.SomeByte;
            Array.Copy(BitConverter.GetBytes(this.SomeInt), 0,
                output, 1, 4);
            Array.Copy(BitConverter.GetBytes(this.SomeShort), 0,
                output, 5, 2);
            output[7] = this.SomeByte2;
            return output;
        }
        set
        {
            byte[] input = value;
            this.SomeByte = input[0];
            this.SomeInt = BitConverter.ToInt32(input, 1);
            this.SomeShort = BitConverter.ToInt16(input, 5);
            this.SomeByte2 = input[7];
        }
    }
}

基本上,它在APIStruct属性中自己进行打包/解包。

票数 6
EN

Stack Overflow用户

发布于 2009-08-25 05:09:44

处理这类问题的最简单方法与处理位字段的方法相同,只需将您的数据打包到适当数据类型的私有成员(如果是大型成员)中,然后呈现为您解包数据的公共属性。解包操作速度极快,对性能的影响很小。对于您的特定类型,以下内容可能是您想要的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public struct SomeStruct
{
    private long data;

    public byte SomeByte { get { return (byte)(data & 0x0FF); } }
    public int SomeInt { get { return (int)((data & 0xFFFFFFFF00) << 8); } }
    public short SomeShort { get { return (short)((data & 0xFFFF0000000000) << 40); } }
    public byte SomeByte2 { get { return (byte)((data & unchecked((long)0xFF00000000000000)) << 56); } }
}

对于一些结构,甚至这种方法也不可行,因为结构的定义方式令人遗憾。在这些情况下,通常必须使用字节数组作为数据的blob,元素可以从中解包。

EDIT:对我所说的不能使用这个简单方法处理的结构进行扩展。当你不能像这样做简单的打包/解包时,你需要手动封送不规则的结构。这可以在调用pInvoked应用编程接口时使用手动方法或使用自定义封送拆收器来完成。下面是一个自定义封送程序的示例,可以很容易地适应现场手动封送处理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System.Runtime.InteropServices;
using System.Threading;

public class Sample
{
    [DllImport("sample.dll")]
    public static extern void TestDataMethod([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TestDataMarshaler))] TestDataStruct pData);
}

public class TestDataStruct
{
    public byte data1;
    public int data2;
    public byte[] data3 = new byte[7];
    public long data4;
    public byte data5;
}

public class TestDataMarshaler : ICustomMarshaler
{
    //thread static since this could be called on 
    //multiple threads at the same time.
    [ThreadStatic()]
    private static TestDataStruct m_MarshaledInstance;

    private static ICustomMarshaler m_Instance = new TestDataMarshaler();

    public static ICustomFormatter GetInstance(string cookie)
    {
        return m_Instance;
    }

    #region ICustomMarshaler Members

    public void CleanUpManagedData(object ManagedObj)
    {
        //nothing to do.
    }

    public void CleanUpNativeData(IntPtr pNativeData)
    {
        Marshal.FreeHGlobal(pNativeData);
    }

    public int GetNativeDataSize()
    {
        return 21;
    }

    public IntPtr MarshalManagedToNative(object ManagedObj)
    {
        m_MarshaledInstance = (TestDataStruct)ManagedObj;
        IntPtr nativeData = Marshal.AllocHGlobal(GetNativeDataSize());

        if (m_MarshaledInstance != null)
        {
            unsafe //unsafe is simpler but can easily be done without unsafe if necessary
            {
                byte* pData = (byte*)nativeData;
                *pData = m_MarshaledInstance.data1;
                *(int*)(pData + 1) = m_MarshaledInstance.data2;
                Marshal.Copy(m_MarshaledInstance.data3, 0, (IntPtr)(pData + 5), 7);
                *(long*)(pData + 12) = m_MarshaledInstance.data4;
                *(pData + 20) = m_MarshaledInstance.data5;
            }
        }
        return nativeData;
    }

    public object MarshalNativeToManaged(IntPtr pNativeData)
    {
        TestDataStruct data = m_MarshaledInstance;
        m_MarshaledInstance = null; //clear out TLS for next call.

        if (data == null) data = new TestDataStruct(); //if no in object then return a new one

        unsafe //unsafe is simpler but can easily be done without unsafe if necessary
        {
            byte* pData = (byte*)pNativeData;
            data.data1 = *pData;
            data.data2 = *(int*)(pData + 1);
            Marshal.Copy((IntPtr)(pData + 5), data.data3, 0, 7);
            data.data4 = *(long*)(pData + 12);
            data.data5 = *(pData + 20);
        }
        return data;
    }

    #endregion
}

对于包含这些结构的数组,除非数组大小固定,否则不能使用自定义封送处理,但是使用相同的技术将数组数据作为一个整体进行手动封送处理相对容易。

票数 4
EN

Stack Overflow用户

发布于 2009-08-27 07:11:43

您是否绝对需要特定的布局,或者可以简单地将大小定为8?

我这样问是因为布局如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[StructLayout(LayoutKind.Explicit, Size=8)]
public struct SomeStruct
{
   [FieldOffset(0)]
   public byte SomeByte;
   [FieldOffset(1)]
   public int SomeInt;
   [FieldOffset(5)]
   public short SomeShort;
   [FieldOffset(7)]
   public byte SomeByte2;
}

具有未对齐的字段,这可能是导致您的问题的原因。

如果你能“重新安排”事情,那么这对你来说可能是可行的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[StructLayout(LayoutKind.Explicit, Size=8)]
public struct SomeStruct
{
   [FieldOffset(0)]
   public byte SomeByte;
   [FieldOffset(1)]
   public byte SomeByte2;
   [FieldOffset(2)]
   public short SomeShort;
   [FieldOffset(4)]
   public int SomeInt;
}

当我在模拟器上测试它时,它工作得很好。

显然,除非您愿意允许重新排列,否则您无能为力。

This answerthis old article会强烈指示您必须至少将结构按其大小的倍数对齐(我尝试使用偏移量为2的整数对齐,但这也触发了错误)

考虑到您需要与外部定义的数据进行互操作,那么以下可能是您最简单的解决方案:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[StructLayout(LayoutKind.Explicit, Size=8)]
public struct SomeStruct
{ 
   [FieldOffset(0)] private byte b0;
   [FieldOffset(1)] private byte b1;
   [FieldOffset(2)] private byte b2;
   [FieldOffset(3)] private byte b3;
   [FieldOffset(4)] private byte b4;
   [FieldOffset(5)] private byte b5;
   [FieldOffset(6)] private byte b6;
   [FieldOffset(7)] private byte b7;

   // not thread safe - alter accordingly if that is a requirement
   private readonly static byte[] scratch = new byte[4];       

   public byte SomeByte 
   { 
       get { return b0; }
       set { b0 = value; }
   }

   public int SomeInt
   {
       get 
       { 
           // get the right endianess for your system this is just an example!
           scratch[0] = b1;
           scratch[1] = b2;
           scratch[2] = b3;
           scratch[3] = b4;
           return BitConverter.ToInt32(scratch, 0);
       }
   }

   public short SomeShort
   {
        get 
        { 
            // get the right endianess for your system this is just an example!
            scratch[0] = b5;
            scratch[1] = b6;
            return BitConverter.ToInt16(scratch, 0);
        }
    }

    public byte SomeByte2 
    { 
        get { return b7; }
        set { b7 = value; }
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1127601

复制
相关文章
Web 框架的替代方案
在本系列第二部分中,Noam 提出了一些模式,说明如何直接用 Web 平台作为框架提供的一些解决方案的替代方案。
深度学习与Python
2022/04/19
2.6K0
Flutter 中FlatButton的替代方案
最新版本的Flutter已将FlatButton标记为过时,我们可以使用 TextButton 或 ElevatedButton 来进行替代,FlatButton 与替代组件的参数会有差异。
xiangzhihong
2023/07/09
6560
Electron中remote模块的替代方案
在Electron12时候被废弃,使用必须配置enableRemoteModule
码客说
2023/09/14
2K0
服务网格的简化替代方案有哪些?
服务网格是一项热门技术,有时甚至被吹捧为微服务成功的必要条件。但是,与许多抽象一样,服务网格可以节省时间,但不会节省学习时间。事实上,许多小型平台团队对服务网格增加的复杂性感到不知所措,尤其是在涉及到长时间的操作时。
用户5166556
2023/03/18
6990
服务网格的简化替代方案有哪些?
Java中的大量if else语句的替代方案
之前写过转载过一篇类似的不错的文章《除代码中的 if-else/switch-case的正确姿势》https://blog.csdn.net/w605283073/article/details/89117561,
明明如月学长
2021/08/31
1.8K0
在制造行业中,ERP是否有更大是施展空间
  其实,在很多企业认为自己已经实现智能制造的时候,提出工业4.0的德国也仅仅是将其作为一个发展的目标。中国制造的总体水平基本在中等的水平,甚至更低,智能制造就更是遥不可及的。
明象ERP
2019/03/01
6330
Linux 中 cron 系统的 4 种替代方案
cron 适用于长期重复任务。如果你设置了一个工作任务,它会从现在开始定期运行,直到计算机报废为止。但有些情况下你可能只想设置一个一次性命令,以备不在计算机旁时该命令可以自动运行。这时你可以选择使用 at 命令。
用户1880875
2021/09/07
2.5K0
还在用Jenkins?看看这些替代方案,是否更适合你!
来源 | dzone.com/articles/13-jenkins-alternatives-for-continuous-integration
程序猿DD
2021/07/13
2.8K0
还在用Jenkins?看看这些替代方案,是否更适合你!
HyStrix替代方案限流降级框架 Sentinel 的原理和实践
有 A 和 B 两个服务,服务 A 作为业务访问的入口直接暴露给用户使用,服务 B 由 A 调用,负责查询一部分供应商的信息,并在设定时间内返回。这时由于出现某种原因,导致业务B的响应时间超时,需要5s才能获取到供应商的查询信息。即使我们忽略其它操作的时间,这也足以带给用户非常差的体验。
用户5927304
2019/09/17
3.7K0
HyStrix替代方案限流降级框架 Sentinel 的原理和实践
还在用Jenkins?看看这些替代方案,是否更适合你!
来源 | dzone.com/articles/13-jenkins-alternatives-for-continuous-integration
路人甲Java
2021/08/20
1.6K0
还在用Jenkins?看看这些替代方案,是否更适合你!
onpropertychange替代方案[通俗易懂]
大家好,又见面了,我是你们的朋友全栈君。 onpropertychange替代方案
全栈程序员站长
2022/08/01
1.3K0
判断链表中是否有环
操作一:定义了两个变量来记录,A一个一次走一步,B一个一次走两步,如果有环B必然会追上A。如果无环B必然会先遍历完。
忧愁的chafry
2022/10/30
1.5K0
判断链表中是否有环
Base:Acid的替代方案
作者:DAN PRITCHETT 译者:java达人 来源:https://queue.acm.org/detail.cfm?id=1394128(点击阅读原文前往) 在数据库分区中,以一致性换取可
java达人
2018/03/26
2.3K0
Base:Acid的替代方案
Hugo .GitInfo 的替代方案
今天有人问我博客页脚 footer 里的 git hash 是怎么显示的,就是页面底部里的 69d6ffe 这一串数字。
eallion
2022/12/20
1.9K0
Hugo .GitInfo 的替代方案
大数据计算中复杂存储过程的替代方案
以往的数据结构和业务逻辑比较简单,所以单条SQL语句就可以实现业务的需要。但随着技术的进步,用户计算的复杂程度也越来越高。要实现复杂的计算,单条SQL语句就显得不是很够了。将一个复杂目标分解为几个有逻辑、清晰、可执行的步骤,数据库开发人员对循环和判断语句、多层分支以及更精确的数据横向操作有了额外的需要。基于这些需要,我们引入了存储过程。
Kevin Chen
2018/06/04
6.4K6
大数据计算中复杂存储过程的替代方案
.NET Core中的包、元包与框架
.NET Core是一个由NuGet包组成的平台。一些产品受益于细粒度包的定义,也有一些受益于粗粒度包的定义。为了适应这种二重性,.NET Core平台被分为一组细粒度的包(package)以及一些被称为元包(metapackage)的较粗粒度的包。
雪飞鸿
2018/09/05
1.1K0
.NET Core中的包、元包与框架
【React】417- React中componentWillReceiveProps的替代升级方案
因为最近在做一个逻辑较为复杂的需求,在封装组件时经常遇到父组件props更新来触发子组件的state这种情景。在使用componentWillReceiveProps时,发现React官网已经把componentWillReceiveProps重名为UNSAFE_componentWillReceiveProps,但是我发现了getDerivedStateFromProps可以替代,却又被一篇博客告知这个也尽量别使用。因为组件一旦使用派生状态,很有可能因为没有明确的数据来源导致出现一些bug和不一致性。既然提倡避免使用,肯定也会有相应的解决方案。
pingan8787
2019/11/26
2.9K0
点击加载更多

相似问题

在IE 7中,是否有CSS空白属性的替代方案?

16

是否有android.net.rtp包的替代方案

13

在Microsoft中是否有ActiveX的替代方案?

25

在didSet中是否有SwiftUI的替代方案?

12

是否有APN的替代方案

20
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文