2010-11-25 46 views
0

以下代码在从C#调用时起作用,但效率不高,因为我从受管理的世界获取数据 ,创建本地本机副本,调用Win32函数,然后将 数据复制回托管参数,返回给调用者。C++/CLI将跟踪句柄转换为Win32的本地指针?

有没有办法完成以下工作?

1)将blinttable UInt32引用参数直接传递给Win32调用?请注意0​​这个Win32调用更新值,我想返回给调用者(即theSerialNumber)在本质上,我可以pin_ptr UInt32参考参数(即theSerialNumber)LPDWORD本地函数可以使用并直接更新其值?

2)将StringBuilder缓冲区直接传递给本地函数?我想我会 需要设置StringBuilder.Capacity = MAX_PATH + 1;但是,我不知道如何pin_ptr到 其内部缓冲区,本地函数将使用和更新。

我一直在这些问题上试验,搜索和敲打我的头几个小时,所以 我真的很感谢你的帮助!

感谢,

迈克


void MCVolume::VolumeInformation(String^ theRootPathName, 
      StringBuilder^% theVolumeName, 
      UInt32% theSerialNumber, 
      UInt32% theMaxComponentLength, 
      MEFileSystemFeature% theFileFlags, 
      StringBuilder^% theFileSystemName) 
{ 

pin_ptr<const wchar_t> rootPathName = PtrToStringChars(theRootPathName); 

wchar_t volumeName[MAX_PATH+1]; 
memset(volumeName, 0x0, MAX_PATH+1); 
wchar_t fileSystemName[MAX_PATH+1]; 
memset(fileSystemName, 0x0, MAX_PATH+1); 
DWORD serialNumber = 0; 
DWORD fileFlags = 0; 
DWORD maxComponentLength = 0; 

//pin_ptr<DWORD> serialNumber = &theSerialNumber; 

if (GetVolumeInformationW(rootPathName, 
      volumeName, 
      MAX_PATH+1, 
      &serialNumber, 
      &maxComponentLength, 
      &fileFlags, 
      fileSystemName, 
      MAX_PATH+1) == false)         
{ 
    // Handle error 
    throw gcnew Exception("GetVolumeInformationW failed."); 
} 

// Send back results... 
theVolumeName = gcnew StringBuilder(marshal_as<String^>(volumeName)); 
theSerialNumber = serialNumber; 
theMaxComponentLength = maxComponentLength; 
theFileFlags = (MEFileSystemFeature) fileFlags; 
theFileSystemName = gcnew StringBuilder(marshal_as<String^>(fileSystemName)); 

回答

0

因为这两个字符串类型(托管字符串和本地WCHAR *)的你无法摆脱编组的两种方式是根本不同的。此外,GC需要跟踪已分配的受管理资源,这就是为什么您总是需要构建一个要发送回受管理世界的对象。

+0

不正确,*您*不必构造要发送回托管世界的对象。使用P/Invoke并让编译器为您完成工作。 – 2010-11-25 11:23:05

0

只需使用来自C++/CLI的P/Invoke。有关更多信息,请参阅here