从.Net MemoryMappedFile提供Win32 HANDLE的属性或方法(如果有的话)是什么?
我有非托管C ++代码,可以读取和写入C风格的文件,例如stdin和stdout。我想使用MemoryMappedFile :: CreateNew创建一个MemoryMappedFile,然后获得一个Win32 HANDLE,可以将其转换为FILE *,以便在非托管C ++中使用。我看到MemoryMappedViewAccessor :: SafeMemoryMappedViewHandle和SafeHandle以及其他可能性,但我没有发现任何说明(或通过示例显示)该句柄可以用作C / C ++程序中的Win32 HANDLE。我只是不确定具体提供Win32 HANDLE。还有其他的可能性,例如使用所有Windows API而不使用.Net,但我问这是否可以使用MemoryMappedFile完成,我确信如果无法使用MemoryMappedFile,我可以使用所有Windows API。
更新:以下是@MichaelGunter转换为C ++的代码。看看Hans Passant的评论,他说这不起作用,但事实并非如此。从safeHandle-> DangerousGetHandle()返回的句柄似乎有效但是当我调用_open_osfhandle来转换句柄时它失败了。
MemoryMappedFile^ mmf = nullptr;
try { mmf = MemoryMappedFile::CreateNew("testmap", 10000, MemoryMappedFileAccess::ReadWrite); }
catch (Object^ ex)
{
// show error
return;
}
SafeMemoryMappedFileHandle^ safeHandle = mmf->SafeMemoryMappedFileHandle;
bool success = false;
safeHandle->DangerousAddRef(success);
if (!success)
{
// show error
return;
}
IntPtr handle = safeHandle->DangerousGetHandle();
if (safeHandle->IsInvalid)
{
// show error
return;
}
pin_ptr<const wchar_t> wchstr = PtrToStringChars(Message);
if (!Put((intptr_t)handle, const_cast<wchar_t*>(wchstr)))
{
// show error
return;
}
safeHandle->DangerousRelease();
这就是“Put”功能。
BOOL Put(intptr_t h, wchar_t* Message) {
int fd = _open_osfhandle(h, 0);
if (fd < 1)
return FALSE;
FILE * fp = _wfdopen(fd, L"w");
fputws(Message, fp);
return TRUE;
}
MemoryMappedFile::SafeMemoryMappedFileHandle Property 文档说我需要安全许可,所以我在几个地方使用了以下内容。
[SecurityPermissionAttribute(SecurityAction::LinkDemand, UnmanagedCode = true)]
答案 0 :(得分:0)
给定MemoryMappedFile:
public class PerformanceCounterDisplay : MonoBehaviour
{
private PerformanceCounter _cpuCounter;
private PerformanceCounter _ramCounter;
[SerializeField]
private Text _cpuCounterText;
[SerializeField]
private Text _ramCounterText;
void Start()
{
_cpuCounter = new PerformanceCounter("Process", "% Processor Time", "_Total");
_ramCounter = new PerformanceCounter("Memory", "Available MBytes", "_Total");
_cpuCounterText.text = GetCpuUsage();
_ramCounterText.text = GetRamUsage();
}
void Update()
{
_cpuCounterText.text = GetCpuUsage();
_ramCounterText.text = GetRamUsage();
}
public string GetCpuUsage()
{
try
{
return "CPU: " + _cpuCounter.NextValue() + "%";
}
catch (Exception eh)
{
Debug.LogError("Cannot get infomation about this PC's CPU");
}
return "";
}
public string GetRamUsage()
{
try
{
return "RAM: " + _ramCounter.NextValue() + "MB";
}
catch (Exception eh)
{
Debug.LogError("Cannot get infomation about this PC's RAM");
}
return "";
}
}
获得“安全”手柄。只要手柄处于使用状态,请存放此安全手柄。
MemoryMappedFile mmf = ...;
添加对句柄的引用,使其不被回收:
SafeMemoryMappedFileHandle safeHandle = mmf.SafeMemoryMappedFileHandle;
获取原始句柄:
bool success = false;
safeHandle.DangerousAddRef(ref success);
if (!success)
throw new InvalidOperationException("Failed to addref handle.");
完成原始手柄后,释放安全手柄:
IntPtr handle = safeHandle.DangerousGetHandle();
答案 1 :(得分:0)
虽然您可以获取内存映射文件对象的句柄(如Michael的回答中所述),但您将无法将此句柄传递给__open_osfhandle
,因为无法使用内存映射文件对象,就好像它是一个文件对象。也就是说,你无法读取或写入句柄;它只能 用于将文件映射对象的视图映射到内存中。
直接使用Win32 API不会有任何区别。文件映射对象根本不提供您正在寻找的功能。
相反,您应该尝试使用管道对象。如果您不尝试移动文件指针,则管道可以被视为文件。我相信Microsoft的C运行时可以接受管道句柄来代替文件句柄,即使文档中没有提到这一点。