The following code works when called from C#, but it seems inefficient because I take the data from the managed world, make local native copies of it, call the Win32 function, and then copy the data back into managed parameters, which are returned to the caller.
Is there a way to accomplish the following?
1) Pass the blittable UInt32 reference parameters directly to the Win32 call? Please note that this Win32 call updates values, which I want to return to the caller (i.e. theSerialNumber) In essense, can I pin_ptr the UInt32 reference parameter (i.e. theSerialNumber) as LPDWORD that the native function can use and directly update its value?
2) Pass the StringBuilder buffers directly to the native function? I imagine that I would need to set StringBuilder.Capacity = MAX_PATH+1; But, I have no idea how to pin_ptr to its internal buffer, which the native function would use and update.
I have be开发者_高级运维en experimenting, searching, and banging my head on these questions for hours, so I really would appreciate your helP!
Thanks,
Mike
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));
You cannot get rid of Marshalling both ways since both of the string types (managed string and native wchar*) are fundamentally different. Furthermore, GC needs to keep track of the managed resources that have been allocated and that's why you will always need to construct a System::String^
object to be sent back to the managed world.
Just use P/Invoke from C++/CLI. See here for more information.
精彩评论