用于指针的C#非托管嵌套结构声明 [英] C# unmanaged nested structure declaration for use with pointers

查看:87
本文介绍了用于指针的C#非托管嵌套结构声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有很多用C/C ++编写的遗留代码,用于在共享内存结构中维护数据.在C/C ++实现中,对于许多功能,我们得到一个指向共享内存地址的指针,然后将该指针转换为该共享内存中包含的结构类型.

我需要将相同的接口移植"到C#.要求是我们不能更改任何C/C ++实现,并且接口用于近乎实时地访问数据(因此性能成为问题).许多数据结构包含其他用户定义的结构的嵌套结构.访问数据的主要方法是指向结构,然后直接访问所需的元素.

我的问题是如何在C#中创建完全不受管理的等效数据结构,并且可以在C#中使用指针.在C#中,可以使用fixed属性创建嵌套结构,但是该属性仅支持基本数据类型,您不能对用户定义的类型使用fixed关键字. Web上的大多数示例都使用封送处理来访问数据元素,但是这些示例中的声明样式使数据结构得以管理,因此不能用作指针.

以下是需要移植到C#的C/C ++实现的简单示例.

有没有人有将其转换为C#实现的方法,该方法创建了一个纯非托管的数据结构,可以使用指针将其作为不安全的方法进行访问?

We have a lot of legacy code written in C/C++ that maintains data in shared memory structures. In the C/C++ implementations, for a lot of functions, we get a pointer to the shared memory address then cast that pointer to the type of structure that is contained in that shared memory.

I have a need to "port" the same interface to C#. The requirements are that we cannot change any of the C/C++ implementation and the interfaces are used to access the data in near real time (so performance is an issue). A lot of the data structures contain nested structures of other user defined structures. The primary way to access the data is to get a point to the structure then directly access the desired elements.

My problem is how to create equivalent data structures in C# that are completely unmanaged and can be used in C# by pointers. In C#, nested structures can be created using the fixed attribute, but that attribute only supports primitive data types, you cant use the fixed keyword with user defined types. Most of the examples on the Web use marshaling to access the data elements, but the declaration style in those examples causes the data structure to be managed so it cant be used as pointers.

The following is a simple example of the C/C++ implementation that needs ported to C#.

Does anyone have a method for converting this to a C# implementation that creates a purely unmanaged data structure that can be access as unsafe with pointers?

// Structures.cpp : Defines the entry point for the console application. //

''#include "StdAfx.h"

typedef struct inner_struct { int a; float b; char text[16]; } InnerStruct;

''#define NUMELEMENTS 20

typedef struct outer_struct { int flag; int num; InnerStruct data[NUMELEMENTS]; } OuterStruct;

void *fSharedMemory();

int _tmain(int argc, _TCHAR* argv[]) { int a;

  OuterStruct *data = NULL;

  data = (OuterStruct *)fSharedMemory();

  while (true)
  {
    if (data->flag)
        for (int i=0; i<data->num; i++) {
            a = data->data[i].a;
        }

    Sleep(100);
  }

  return 0;

}



我觉得我在这里想念什么.如果有足够的时间和金钱,我们会将所有实现重写为托管代码,但是我必须相信,我不是唯一一个必须与遗留代码进行交互的人.



I feel like I am missing something here. Given enough time and money we would rewrite all of the implementation as managed code, but I have to believe I am not the only one who has to interface with legacy code.

推荐答案

不确定我是否理解您的问题,但是我认为您做出了一个错误的假设,即不安全的代码与非托管的代码相同.这是错误的.当您想在C#中使用指针算术时,关键字unsafe是必需的,但是由于C#是托管语言,因此它始终与托管数据一起使用.

我的意思是,无论是否使用指针,在C#中使用的类的任何实例都将分配在托管堆中.考虑到这一点,这就是互操作的工作方式:

您有一个指向非托管对象的指针,并且希望能够在C#中获得该对象.好了,您将必须在C#中声明这些类并使用Marshal.PtrToStructure以获得该对象的托管版本,您可以在C#中使用它.

现在,您在C#中拥有一个托管对象,并希望将其传递给非托管代码.好了,您必须调用Marshal.StructureToPtr才能将托管对象的副本复制到非托管内存块中.

另一方面,我不确定,但是也许这两个类将满足您发布的代码片段的要求:

Not sure if I have understood your question, but I think you are making a bad assumption cosindering that unsafe code is the same as unmanaged code. This is wrong. The keyword unsafe is required when you want to use pointer arithmetic in C#, but since C# is a managed language, it always works with managed data.

What I mean is that, whether you use pointers or not, any instance of a class which you use in C# will be allocated in the managed heap. Having this in mind, this is how interop works:

You have a pointer to an unmanaged object, and you want to be able to get this object in C#. Well, you will have to declare the classes in C# and use Marshal.PtrToStructure in order to get a managed version of that object which you can use in C#.

Now, you have a managed object in C# and want to pass it to unmanaged code. Well, you will have to call Marshal.StructureToPtr in order to make a copy of your managed object into an unmanaged block of memory.

On the other hand, I am not sure of this, but maybe these two classes will meet the requirements for the code snippet you have posted:

[StructLayout(LayoutKind.Sequential)]
class InnerStruct
{
    [MarshalAs(UnmanagedType.I4)]
    public int a;
    public float b;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=16)]
    public byte[] text;
}

[StructLayout(LayoutKind.Sequential)]
class OuterStruct
{
    [MarshalAs(UnmanagedType.I4)]
    public int flag;
    [MarshalAs(UnmanagedType.I4)]
    public int num;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
    public InnerStruct[] data;
}



请记住,您不需要在C#中使用指针.无论是否使用它们,C#都只能与托管对象一起使用,因此将它们用作任何其他托管对象,然后再使用Marshal类.



Remember you don''t need to use pointers in C#. Whether you use them or not, C# only works with managed objects, so use them as any other managed object and then use Marshal class.


这篇关于用于指针的C#非托管嵌套结构声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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