18

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

.NET 2.0 版怎么可能?

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

4

6 回答 6

14

更新:嘿,这是我刚刚找到的一个完整实现的页面。


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

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

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

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;
}
于 2009-05-29T10:01:38.873 回答
6

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

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

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

.NET Remoting 简单英语

.NET Remoting 一个简单的例子

于 2009-01-13T17:10:02.487 回答
3

共享内存是唯一的选择吗?两个 .NET 进程有多种通信方式。他们之中有一些是:

  • .NET Remoting Object - 允许对象跨进程相互交互。这里有一个很好的代码示例
  • Microsoft 消息队列 (MSMQ) - 进程之间的共享消息队列。MSMQ 将作为另一个 Windows 服务运行。
于 2009-01-13T17:11:04.700 回答
3

您还可以在 C# 应用程序中导入 win32 函数来替代 C++/CLI:

[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);
于 2011-12-12T11:58:28.013 回答
1

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

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

感谢您的回答

于 2009-01-13T18:31:14.337 回答
0

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

于 2016-07-12T08:16:12.733 回答