如何在.NET中实现共享内存?

发布于 2024-07-11 21:57:11 字数 113 浏览 5 评论 0原文

我有一个 C++.NET 应用程序和一个 C#.NET 应用程序。 我希望他们通过共享内存进行通信。

在 .NET 2.0 版本中怎么可能?

主要是想共享一个队列对象。

I have a C++.NET app and a C#.NET app. I would like them to communicate via shared memory.

How is it possible in .NET version 2.0 ?

Mainly want to share a queue object.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

笑梦风尘 2024-07-18 21:57:11

更新:嘿,这是我刚刚发现的一个具有完整实现的页面


使用 C++/CLI,按照普通 C++ API 设置共享内存非常容易(C++/CLI 能够与托管和本机 HEAP/内存引用进行交互)。 然后可以使用 UnmanagedMemoryStream 将 Stream 对象公开给 C#。

我没有附加 .h 文件,但您可以相当容易地推断出 pmap 的本机 typedef 的布局;)。 您可能还想根据您的读取器/写入器用例评估 BufferedStream 的可能使用。 该代码来自一个我不再使用的项目,所以我不记得它的错误回归的状态。

这是 C++/CLI 类,它建立文件映射并公开 UnmanagedMemoryStream;

public ref class MemMapp
{
    public:
        __clrcall MemMapp(String^ file)  
        { 
            map = NULL;

            if(!File::Exists(file)) throw gcnew ApplicationException("Can not find file " + file);

            marshal_context^ x = gcnew marshal_context();
            const char *nname = x->marshal_as<const char*>(file);

            map = (pmapped) malloc(sizeof(mapped));
            ZeroMemory(map, sizeof(mapped));
            map->name = strdup(nname);
            InitMap(map);
        }
        void __clrcall MapBytes(long long loc, long length)
        {
            map->low = loc & 0xffffffff;
            map->high = (loc >> 32) & 0xffffffff;
            map->size = length & 0xffffffff;
            if(!GetMapForFile(map))
                throw gcnew ApplicationException("can not map range " + loc + " :" + length);

            if(map->size = 0)
                map->size = MAXMAX&0xffffffff;

        }
        UnmanagedMemoryStream ^View()
        { 
            return gcnew UnmanagedMemoryStream((unsigned char *) map->blok, map->size, map->size, FileAccess::Read); 
        }
        long long __clrcall FileSize()
        {
            DWORD high, low;
            long long rv;

            low = GetFileSize(map->hFile, &high);
            maxmax = high;
            maxmax << 32;
            maxmax += low;

            rv = high;
            rv << 32;
            rv = rv & low;
            return rv;
        }
        property unsigned int MinBufSiz { unsigned int get() { return map->dwbufz; } }
        property long long BufBase { long long get() { return (map->high << 32) + map->low; } }
        property long long BufLim { long long get() { return ((map->high << 32) + map->low) + map->size; } }
        property long long MAXMAX { long long get() { return maxmax; } }
        static MemMapp() { }
        __clrcall ~MemMapp() { if(map != NULL) { CloseMap(map); free(map->name); free(map); map = NULL; } }
    protected:
        __clrcall !MemMapp() { if(map != NULL) { CloseMap(map); free(map->name); free(map); map = NULL; } }
        pmapped map;
        long long maxmax;
};

至少这是 CLoseMap...我刚刚找到它...它不是用 /CLR 编译的


bool CloseMap(pmapped map)
{
    if(map->blok != NULL) {
        UnmapViewOfFile(map->blok);
        map->blok = NULL;
    }
    if(map->hMap != INVALID_HANDLE_VALUE && map->hMap != NULL) {
        CloseHandle(map->hMap);
        map->hMap = INVALID_HANDLE_VALUE;
    }
    if(map->hFile != INVALID_HANDLE_VALUE && map->hFile != NULL) {
        CloseHandle(map->hFile);
        map->hFile = INVALID_HANDLE_VALUE;
    }
    return false;
}

Update: Hey, here's a page I just found with a compleate implmentation.


Using C++/CLI, it's quite easy to setup shared memory as per normal C++ API (C++/CLI being able to interact with the managed and native HEAP/memory references). The UnmanagedMemoryStream can then be used to expose a Stream object to C#.

I did not attach the .h file, but you can infer the layout of the pmapped native typedef fairly easially ;). You may also want to evaluate the possible use of a BufferedStream depending on your reader/writer use case. And the code is from a project which I do not use any more so I can not remember the status of it's bug regression.

Here's the C++/CLI class which establishes a file mapping and exposes an UnmanagedMemoryStream;

public ref class MemMapp
{
    public:
        __clrcall MemMapp(String^ file)  
        { 
            map = NULL;

            if(!File::Exists(file)) throw gcnew ApplicationException("Can not find file " + file);

            marshal_context^ x = gcnew marshal_context();
            const char *nname = x->marshal_as<const char*>(file);

            map = (pmapped) malloc(sizeof(mapped));
            ZeroMemory(map, sizeof(mapped));
            map->name = strdup(nname);
            InitMap(map);
        }
        void __clrcall MapBytes(long long loc, long length)
        {
            map->low = loc & 0xffffffff;
            map->high = (loc >> 32) & 0xffffffff;
            map->size = length & 0xffffffff;
            if(!GetMapForFile(map))
                throw gcnew ApplicationException("can not map range " + loc + " :" + length);

            if(map->size = 0)
                map->size = MAXMAX&0xffffffff;

        }
        UnmanagedMemoryStream ^View()
        { 
            return gcnew UnmanagedMemoryStream((unsigned char *) map->blok, map->size, map->size, FileAccess::Read); 
        }
        long long __clrcall FileSize()
        {
            DWORD high, low;
            long long rv;

            low = GetFileSize(map->hFile, &high);
            maxmax = high;
            maxmax << 32;
            maxmax += low;

            rv = high;
            rv << 32;
            rv = rv & low;
            return rv;
        }
        property unsigned int MinBufSiz { unsigned int get() { return map->dwbufz; } }
        property long long BufBase { long long get() { return (map->high << 32) + map->low; } }
        property long long BufLim { long long get() { return ((map->high << 32) + map->low) + map->size; } }
        property long long MAXMAX { long long get() { return maxmax; } }
        static MemMapp() { }
        __clrcall ~MemMapp() { if(map != NULL) { CloseMap(map); free(map->name); free(map); map = NULL; } }
    protected:
        __clrcall !MemMapp() { if(map != NULL) { CloseMap(map); free(map->name); free(map); map = NULL; } }
        pmapped map;
        long long maxmax;
};

Here's CLoseMap at least... I just found it... it was not compiled with /CLR


bool CloseMap(pmapped map)
{
    if(map->blok != NULL) {
        UnmapViewOfFile(map->blok);
        map->blok = NULL;
    }
    if(map->hMap != INVALID_HANDLE_VALUE && map->hMap != NULL) {
        CloseHandle(map->hMap);
        map->hMap = INVALID_HANDLE_VALUE;
    }
    if(map->hFile != INVALID_HANDLE_VALUE && map->hFile != NULL) {
        CloseHandle(map->hFile);
        map->hFile = INVALID_HANDLE_VALUE;
    }
    return false;
}
征棹 2024-07-18 21:57:11

您的应用程序可以通过多种方式进行通信。 最流行的是远程处理和管道。 两者都有几个例子,在您选择一个之前,您应该考虑其优点和缺点,例如可移植性。 以下是一些有用的链接:

使用命名管道在 .NET 中进行进程间通信,第 1 部分

使用命名管道在 .NET 中进行进程间通信,第 2 部分

简单英语的 .NET 远程处理

.NET 远程处理与简单示例

There are several options for your applications to communicate. The most popular are Remoting and Pipes. There are several examples for both and before you choose one you should consider the pros and cons such as portability. Here are some useful links:

Inter-Process Communication in .NET Using Named Pipes, Part 1

Inter-Process Communication in .NET Using Named Pipes, Part 2

.NET Remoting in Simple English

.NET Remoting with an easy example

看轻我的陪伴 2024-07-18 21:57:11

共享内存是唯一的选择吗? 两个 .NET 进程可以通过多种方式进行通信。 其中一些是:

  • .NET Remoting Object - 允许对象跨进程相互交互。 此处有一个很好的代码示例
  • Microsoft 消息队列 (MSMQ) - 一个共享进程之间的消息队列。 MSMQ 将作为另一个 Windows 服务运行。

Is shared memory the only option? There are many ways for two .NET processes to communicate. Some of them are:

  • .NET Remoting Object - Allow objects to interact with each other across processes. There is a good code sample here
  • Microsoft Message Queue (MSMQ) - A shared message queue between processes. MSMQ will run as another Windows Service.
蹲墙角沉默 2024-07-18 21:57:11

您还可以使用 C++/CLI 的替代方案,在 C# 应用程序中导入 win32 函数:

[DllImport ("kernel32.dll", SetLastError = true)]
  static extern IntPtr CreateFileMapping (IntPtr hFile,
                                          int lpAttributes,
                                          FileProtection flProtect,
                                          uint dwMaximumSizeHigh,
                                          uint dwMaximumSizeLow,
                                          string lpName);

  [DllImport ("kernel32.dll", SetLastError=true)]
  static extern IntPtr OpenFileMapping (FileRights dwDesiredAccess,
                                        bool bInheritHandle,
                                        string lpName);

  [DllImport ("kernel32.dll", SetLastError = true)]
  static extern IntPtr MapViewOfFile (IntPtr hFileMappingObject,
                                      FileRights dwDesiredAccess,
                                      uint dwFileOffsetHigh,
                                      uint dwFileOffsetLow,
                                      uint dwNumberOfBytesToMap);
  [DllImport ("Kernel32.dll")]
  static extern bool UnmapViewOfFile (IntPtr map);

  [DllImport ("kernel32.dll")]
  static extern int CloseHandle (IntPtr hObject);

You also have an alternative to C++/CLI as importing win32 functions in your C# app:

[DllImport ("kernel32.dll", SetLastError = true)]
  static extern IntPtr CreateFileMapping (IntPtr hFile,
                                          int lpAttributes,
                                          FileProtection flProtect,
                                          uint dwMaximumSizeHigh,
                                          uint dwMaximumSizeLow,
                                          string lpName);

  [DllImport ("kernel32.dll", SetLastError=true)]
  static extern IntPtr OpenFileMapping (FileRights dwDesiredAccess,
                                        bool bInheritHandle,
                                        string lpName);

  [DllImport ("kernel32.dll", SetLastError = true)]
  static extern IntPtr MapViewOfFile (IntPtr hFileMappingObject,
                                      FileRights dwDesiredAccess,
                                      uint dwFileOffsetHigh,
                                      uint dwFileOffsetLow,
                                      uint dwNumberOfBytesToMap);
  [DllImport ("Kernel32.dll")]
  static extern bool UnmapViewOfFile (IntPtr map);

  [DllImport ("kernel32.dll")]
  static extern int CloseHandle (IntPtr hObject);
北笙凉宸 2024-07-18 21:57:11

我认为 .NET v2.0 没有对共享内存的内置支持。
我们最多可以调用 CreateFileMapping 和 MapViewOfFile API。

在我的场景中,IPC 必须在一台机器上进行。 所以管道是目前最快的选择。

感谢您的回答

I suppose .NET v2.0 does not have in-built support for shared memory.
At most we can PInvoke the CreateFileMapping and MapViewOfFile APIs.

In my scenario the IPC must take place on a single machine. So pipes is the fastest option as of now.

Thanks for the answers

深巷少女 2024-07-18 21:57:11

看看这个[链接]:
http://www.albahari.com/nutshell/ch22.aspx
在共享内存包装器中你可以找到答案。

Take a look at this [link]:
http://www.albahari.com/nutshell/ch22.aspx
in Shared memory wrapper you can find your answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文