On Apr 26, 1:16 pm, "Willy Denoyette [MVP]"
<willy.denoye...@telenet.be> wrote:
> Mind to post your code, or at least a shot/complete sample that illustrates
> the issue.
>
> Willy.
Willy,
For P/Invoke, I do the following on the managed side:
// used to shuttle the data to the unmanaged world
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SomeBuffer
{
public IntPtr data;
public int len;
}
[DllImport("Unmanaged.dll", CharSet = CharSet.Ansi)]
public static extern void SaveData(string name, ref SomeBuffer
data);
I then allocate the buffer ala:
SomeBuffer CreateBuffer(byte[] value)
{
SomeBuffer sb = new SomeBuffer();
sb.length = data.Length;
sb.buffer = Marshal.AllocHGlobal(sb.length);
Marshal.Copy(value, 0, sb.buffer, sb.length);
return sb;
}
and invoke SaveData() with a created SomeBuffer to house the value
byte array.
For C++ Interop, on the managed (c++/cli) side, the function is:
void SaveData( String^ name, array<byte>^ value)
{
localName =
(char*)Marshal::StringToHGlobalAnsi(name).ToPointer(); // marshal the
name
pin_ptr<byte> ptr = &value[0]; // pin the value buffer
SomeBuffer sb;
sb.buffer = (void*)ptr;
sb.length = bytes.Length;
unmanagedImpl->SaveData( localName, &sb); // issue the unmanaged
call
Marshal::FreeHGlobal(IntPtr(localName)); // free the
marshalled string buffer
}
Assume the unmanaged SaveData method copies the incoming SomeBuffer
data to process in both approaches and that the prototype is:
void SaveData (LPCSTR name, SomeBuffer* value);
Thanks
Willy Denoyette [MVP] - 27 Apr 2008 20:01 GMT
> On Apr 26, 1:16 pm, "Willy Denoyette [MVP]"
> <willy.denoye...@telenet.be> wrote:
[quoted text clipped - 63 lines]
>
> Thanks
I don't see how CreateBuffer relates to the other functions, you need to
post a complete runable sample.
Anyway, If CreateBuffer is used in the PInvoke case, then the Interop case
should be quite a bit faster than the PInvoke case, you don't copy from
managed to unmanaged in the Interop case, you just pass a pointer to the
pinned array, while in the PInvoke case you copy the managed array to
unmanaged and pass a pointer to this unmanaged array.
PInvoke should be as fast as C++ Interop, if you don't copy, but instead
also pass a pinned pointer.
Willy.
Ben Voigt [C++ MVP] - 01 May 2008 22:01 GMT
> For C++ Interop, on the managed (c++/cli) side, the function is:
>
[quoted text clipped - 3 lines]
> (char*)Marshal::StringToHGlobalAnsi(name).ToPointer(); // marshal the
> name
using an HGLOBAL here is unnecessary, I would instead call PtrToStringChars
and convert. By using a stack buffer you can save the allocate/deallocate
time, and you can always fall back to dynamic allocation if your static
buffer isn't bug enough.
Besides, if that function really is returning an HGLOBAL, you'd need to call
GlobalLock to get a pointer. Let me check the docs...
Oh, brilliant. Microsoft calls the function that wraps LocalAlloc (which
returns an HLOCAL) Marshal.AllocHGlobal. Who needs obfuscation when you
have APIs designed like that?
Also, what /clr:xyz option are you compiling with?
> pin_ptr<byte> ptr = &value[0]; // pin the value buffer
>
[quoted text clipped - 16 lines]
>
> Thanks