我有一个C ++ .NET应用程序和一个C#.NET应用程序。我希望他们通过共享内存进行通信。
.NET版本2.0怎么可能?
主要想要共享一个队列对象。
答案 0 :(得分:13)
更新:嘿,here's a page我刚刚发现了一个完整的实施。
使用C ++ / CLI,按照普通的C ++ API(C ++ / CLI能够与托管和本机HEAP /内存引用进行交互)设置共享内存非常容易。然后可以使用UnmanagedMemoryStream将Stream对象公开给C#。
我没有附加.h文件,但你可以很容易地推断出pmapped native typedef的布局;)。您可能还想根据读者/编写器用例评估BufferedStream的可能用途。代码来自一个我不再使用的项目,所以我不记得它的bug回归的状态。
这是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;
}
答案 1 :(得分:6)
您的应用程序可以通过多种方式进行通信。最受欢迎的是Remoting和Pipes。有两个例子,在您选择之前,您应该考虑优点和缺点,如可移植性。以下是一些有用的链接:
Inter-Process Communication in .NET Using Named Pipes, Part 1
Inter-Process Communication in .NET Using Named Pipes, Part 2
答案 2 :(得分:3)
共享内存是唯一的选择吗?有两种.NET进程可以通信的方式。其中一些是:
答案 3 :(得分:3)
您还可以在C#app中导入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);
答案 4 :(得分:1)
我认为.NET v2.0没有内置的共享内存支持。 最多我们可以PInvoke CreateFileMapping和MapViewOfFile API。
在我的场景中,IPC必须在一台机器上进行。所以管道是目前最快的选择。
感谢您的回答
答案 5 :(得分:0)
看看这个[链接]: http://www.albahari.com/nutshell/ch22.aspx 在共享内存包装器中,您可以找到答案。