I have a function made in C++ that calls a COM interface’s function
Its signature:
BOOL func(LPWSTR strIn, __out LPWSTR strOut)
{
//initcom
//do something
// release pointers
}
In C#:
[DllImport("funcdll.dll")]
static extern bool func(String strIn, ref String strOut);
// use it
for(int i=0;i<10;i++)
{
if(func(strin, strout))
{
//do something with strout
}
}
I have tested my dll in a C++ console application, it works, but in C# it crashes with an unknown error.
You’ve got three problems that I can see.
cdecland your C# code isstdcall.Now, dealing with these in more detail.
Calling conventions
This is pretty easy to fix. Simple change the C++ code to
stdcall, or the C# code tocdecl. But don’t do both. I’d change the C# code:Unicode/ANSI strings
I presume you are wanting to use Unicode strings since you have explicitly selected them in the C++ code. But P/invoke defaults to marshalling ANSI strings. You can change this again in the
DllImportlike so:Returning a string from C++ to C#
Your current C++ function declaration is so:
The
__outdecorator has no real effect, other than documenting that you want to modify the buffer pointed to bystrOutand have those modifications returned to the caller.Your C# declaration is:
Now,
ref String strOutsimply does not match. Arefstring parameter matches this in C++:In other words the C# code is expecting you to return a new pointer. In fact it will then proceed to deallocate the buffer you returned in
strOutby callingCoTaskMemFree. I’m confident that’s not what you want.Your original C++ code can only return a string to the C# code by modifying the buffer that was passed to it. That code would look like this:
If this is what you want then you should allocate a sufficient buffer in C# in a
StringBuilderobject.If you simply cannot decide in the C# code how big a buffer you need then your best bet is to use a
BSTRto marshal strOut. See this answer for details.