Click here to Skip to main content
15,311,717 members
Please Sign up or sign in to vote.
4.50/5 (2 votes)
See more:
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.
Posted
Updated 22-Nov-10 19:19pm
v2

1 solution

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:

C#
[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;
}


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.
   
Comments
Robert Ammon 30-Nov-10 0:38am
   
Actually, what I have is the reverse of what you have described. I have a pointer to unmanaged memory returned from a call to unmanaged code and I want to "map" a C# structure declaration to that memory and access it via a pointer. If possible, for performance reasons, i would prefer to not marshal the data from unmamanged memory to managed memory. What I would like to do is use the point returned from unmanaged code to access data in unmanaged memory in C#.
_Erik_ 30-Nov-10 8:57am
   
No way. To make this you should declare a C# structure and, therefore, that structure will always be understood as a managed type, and you cannot declare a pointer to a managed type. The only thing you could do is using a byte* and manually calculate the offset and size for each field in the unmanaged object, but you cannot map a C# structure to a pointer becouse, as I have said, a C# structure is always understood as a managed type.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900