CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Apr 2000
    Location
    Atlanta, GA, USA
    Posts
    21

    Shared memory w/ unmanaged DLL

    This is my first excursion into .NET development, so please forgive any novice oversights...

    I'm trying to write a C# application that accesses shared memory in an unmanaged Win32 DLL.

    The Win32 DLL defines the shared memory in such a fashion:

    Code:
    // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    // define shared memory
    //
    // data must be initialized!  data_seg pragma applies only to initialized data.
    #pragma data_seg(".SHAREDMEMORY")
    
    int gshared_nTest = 0;
    
    #pragma data_seg() 
    
    // sets linker switch for shared memory section
    #pragma comment(linker, "/SECTION:.SHAREDMEMORY,RWS");
    How can I get my C# application to access this shared memory? Is it even possible?

    Thanks,
    Jeremy

  2. #2
    Join Date
    Nov 2002
    Location
    Singapore
    Posts
    1,890
    actually for unmanaged stuff !!,

    so what you should do is , if you want the shared memory information then you should create a function which returns the information or array,
    and later on you can access that array in C# by following. C++ array creation is your side !!!


    using System;
    using System.Runtime.InteropServices;

    [StructLayout(LayoutKind.Explicit)]
    public struct Short2DArray
    {
    public const int ElementSize = 2;

    [FieldOffset(0)]
    private int _size0;
    [FieldOffset(4)]
    private int _size1;

    [FieldOffset(8), MarshalAs(UnmanagedType.ByValArray)]
    public readonly short[] shortArray;

    [FieldOffset(8), MarshalAs(UnmanagedType.ByValArray)]
    public readonly byte[] byteArray;

    public Short2DArray(int size0, int size1)
    {
    _size0 = size0;
    _size1 = size1;

    shortArray = new short[size0 * size1];
    byteArray = new byte[size0 * size1 * ElementSize];
    }

    public byte this[int index]
    {
    get { return byteArray[index]; }
    set { byteArray[index] = value; }
    }

    public short this[int index0, int index1]
    {
    get
    {
    if (index0 >= _size0 || index1 >= _size1)
    throw new ArgumentOutOfRangeException();

    return shortArray[index0 * _size0 + index1];
    }
    set
    {
    if (index0 >= _size0 || index1 >= _size1)
    throw new ArgumentOutOfRangeException();

    shortArray[index0 * _size0 + index1] = value;
    }
    }

    public int ShortSize
    {
    get { return _size0 * _size1; }
    }

    public int ShortSize0
    {
    get { return _size0; }
    }
    public int ShortSize1
    {
    get { return _size1; }
    }

    public int ByteSize
    {
    get { return ElementSize * _size0 * _size1; }
    }

    public byte[] GetSafeBytes()
    {
    byte[] ret = new byte[ByteSize];
    Buffer.BlockCopy(byteArray, 0, ret, 0, ByteSize);
    return ret;
    }

    public short[,] GetSafeShorts()
    {
    short[,] ret = new short[_size0, _size1];
    Buffer.BlockCopy(byteArray, 0, ret, 0, ByteSize);
    return ret;
    }
    }



    Paresh
    - Software Architect

  3. #3
    Join Date
    Apr 2000
    Location
    Atlanta, GA, USA
    Posts
    21
    Thanks!!

    I also received this helpful reply from MatiasN on www.gotdotnet.com:


    [Begin quote from MatiasN]

    Yes, you can. But you will need access to the underlying dll that contains the shared memory in order to create functions that can get/set the shared memory values ( or perform whatever action on the shared memory that you need to.

    I thought this was an interesting example, so I quickly created something that should work. Its primitive, but it proves the point. The following code snippet is from a VC++ 7.0 project and this is the main cpp file.
    ( By the way the semi-colon you had on your original #pragma comment line was unnecessary and will cause a compiler warning ).
    Code:
    //================================================= 
    #include "stdafx.h" 
    #pragma data_seg(".SHAREDMEMORY") 
    int gshared_nTest=0; 
    #pragma data_seg() 
    #pragma comment(linker,"/SECTION:.SHAREDMEMORY,RWS") 
    BOOL APIENTRY DllMain( HANDLE hModule, 
                          DWORD  ul_reason_for_call, 
                          LPVOID lpReserved 
                                  ) 
    { 
        return TRUE; 
    } 
    extern "C" __declspec(dllexport) int __stdcall getMyData() 
    { 
          return gshared_nTest; 
    } 
    extern "C" __declspec(dllexport) void __stdcall setMyData( int data ) 
    { 
          gshared_nTest = data; 
    } 
    //================== END OF CPP FILE ================== 
    
    Note: You must declare it as extern "C" in order to prevent the mangling of names. This is absolutely necessary in order to import it into a c# project. 
    
    //================================================= 
    To test this you can create a simple console application with the following code snippet. I put the message box in there so I could run multiple console applications at the same time and pause them so that I could see the shared memory values changing. 
    
    //================================================= 
    
    using System; 
    using System.Windows.Forms; 
    using System.Runtime.InteropServices; 
    
    namespace TestShared 
    { 
          class TestShared 
          { 
                [DllImport(@"C:\VS Projects\Shared\Debug\Shared.dll")] 
                public static extern int getMyData(); 
                [DllImport(@"C:\VS Projects\Shared\Debug\Shared.dll")] 
                public static extern void setMyData(int data); 
    
                [STAThread] 
                static void Main(string[] args) 
                { 
                      setMyData( getMyData() + 100 ); 
                      MessageBox.Show( getMyData().ToString() ); 
                } 
          } 
    }
    -MatiasN

    [End quote from MatiasN]
    Last edited by Jeremy Johnson; April 23rd, 2003 at 03:40 PM.

  4. #4
    Join Date
    Nov 2002
    Location
    Singapore
    Posts
    1,890
    good. yes I had seen that . its actually kind of tough problem when u deal with C++ specially with memory since it has to pass thru several layers to talk with memory.

    Paresh
    - Software Architect

  5. #5
    Join Date
    Apr 2000
    Location
    Atlanta, GA, USA
    Posts
    21
    I've successfully shared Integers, but I'm running into problems when I attempt to share a simple struct.

    Here's what I'm defining in the unmanaged DLL:

    --------------------------------------------------------------
    typedef struct
    {
    int vt;
    int nVal;
    double dVal;
    } BP_SHARED_DATA;

    extern "C" __declspec(dllexport) BP_SHARED_DATA ReadPipe();
    --------------------------------------------------------------

    ReadPipe() is just returning my shared structure (not shown).

    Here's the .NET side of things:

    --------------------------------------------------------------
    public class BrowserPipe
    {
    [StructLayout( LayoutKind.Sequential)]
    public class SHARED_DATA
    {
    public Int32 vt;
    public Int32 nVal;
    public Double dVal;
    };

    [DllImport(@"BrowserPipe.ocx")]
    public static extern SHARED_DATA ReadPipe();
    }

    ---------------------------------------------------------------

    Whenever I call ReadPipe(), I get a "System.NotSupportedException". I've also tried defining "SHARED_DATA" as a struct, but it doesn't solve the problem.

    Any suggestions? Oh, I should mention that I'm using the Compact Framework.

    Thanks!
    Jeremy

  6. #6
    Join Date
    Nov 2002
    Location
    Singapore
    Posts
    1,890
    try using with another kind of Layout strucutre..

    Paresh
    - Software Architect

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured