I have a solution which consists of two projects: a C# console app and a C library. The C library has a function which returns a HRESULT. I need to somehow change this function to get it to return a string to my C# code. This is how it should look:
C#:
[DllImport("MyLib.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern long MyFunction(bunch of params, [MarshalAs(UnmanagedType.BStr)] out string text);
C:
extern "C" HRESULT __declspec(dllexport) MyFunction(bunch of params, BSTR* text)
{
PWSTR finalResult;
//lots of code
(*text) = SysAllocString(finalResult);
//cleanup code
}
I can change both projects. However, there's no way of knowing how big the string will be. Therefore, I've tried allocating the string in the C lib but this lead to access violation exceptions and all sorts of problems. What would be the best way to tackle this?
Wow! almost 3 years and this question doesn't have a proper answer!
The correct way of transfer strings form the unmanaged is, at least on my experience, to combine the StringBuilder
class with an additional parameter representing the size of the "buffer".
Something like this:
// C#
[DllImport("MyLib.dll",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.Cdecl)]
public static extern bool MyFunction(
// other parameters,
StringBuilder buffer,
[MarshalAs(UnmanagedType.U4)] int bufferSize
);
// C:
extern "C" __declspec(dllexport) BOOL MyFunction(bunch of params, LPTSTR* text, unsigned int textSize)
{
char *mySourceString = doSomethingAndReturnString(bunch of params);
if ( textSize < strlen(mySourceString)) {
SetLastError(ERROR_INSUFFICIENT_BUFFER)
return FALSE;
}
strncpy(text, mySourceString, strlen(mySourceString))
return TRUE;
}
And use it this way:
StringBuilder sb = new StringBuilder(128);
while (!NativeMethods.MyFunction(/*other parameters*/, sb, sb.Capacity))
{
if (Marshal.GetLastWin32Error() != 0x7A) {
// throw
}
// Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER
sb.Capacity *= 2;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With