I have a C library that I don't have the source code for that I need to call into from .NET.
The signature of the Query
function I need is:
typedef int LoginID;
typedef const char* XML;
typedef DSQUERYHANDLER* PDSQUERYHANDLER;
typedef ErrCode DSQUERYHANDLER (LoginID lh, void* tag, XML resXML, ErrCode retCode);
Query(LoginID lh, XML queryXML, XML* queryResultXML_out, void* tag, PDSQUERYHANDLER cb);
The C# that I've written to correspond to this is:
delegate ErrCode DSQUERYHANDLER(int lh, IntPtr tag, string resXML, ErrCode retCode);
[DllImport("dllname.dll")]
internal static extern ErrCode Query(int lh, string queryXML, out string queryResultXML_out, IntPtr tag, DSQUERYHANDLER cb);
I don't actually care about the last two parameters and pass IntPtr.Zero
and null
.
When I call Query
, it sets the string that I've given it with the value that I'd expect, but it also crashes with a System.AccessViolationException!
If I change to using StringBuilder
instead of out string
:
[DllImport("dllname.dll")]
internal static extern ErrCode Query(int lh, string queryXML, StringBuilder queryResultXML_out, IntPtr tag, DSQUERYHANDLER cb);
Then it doesn't crash, but the StringBuilder
contains a length of 4, but with different values each time it's run, e.g Èf or p'F.
My Questions
What is the difference between using out string
and StringBuilder
? Also is it possible for me to debug this without access to the internals of the C library?