1

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?

NickL
  • 1,870
  • 2
  • 15
  • 35
  • StringBuilder is not correct, the 4 'characters' you see are actually the const char* pointer value. Using out string is not correct either, the pinvoke marshaller takes on the duty to release the string buffer again and that will fail with AVE because the string was not allocated from the interop heap. You have use out IntPtr instead and recover the string with Marshal.PtrToStringAnsi(). And take on the duty to release the string buffer which you cannot do. Very likely you'll have a permanent memory leak. You'll have to use C++/CLI instead or fix the native code. – Hans Passant Jul 13 '16 at 14:32
  • Thanks @HansPassant. This is all new to me unfortunately... Your suggestion does work, and they provide a function to release strings allocated by their API... Do you want to post your comment as an answer so I can accept it? – NickL Jul 13 '16 at 14:47
  • Pretty sure you now have everything you need to know to answer your question yourself. – Hans Passant Jul 13 '16 at 14:52

1 Answers1

-1

Your problem has been answered here -

DLLImport c++ functions with char* input as and output parameters

I won't repeat information here - please read the above link and this will explain the process for calling your function.

I feel explaining the difference between StringBuilder and String will not help you regarding your issue.

Community
  • 1
  • 1
Neil
  • 1,036
  • 9
  • 18
  • If you think that question answers the OP's question please mark this question as duplicate instead of answering. – Hatted Rooster Jul 13 '16 at 14:49
  • @Gill Bates - I do not have the rep to mark as duplicate. I am just trying to assist here. – Neil Jul 13 '16 at 14:56
  • You can always flag a question as a duplicate, there's no reputation limit on that. – Hatted Rooster Jul 13 '16 at 14:59
  • @Gill Bates - Well, I learn something new everyday. Thanks for pointing that out. I was under the assumption, quite wrongly, that it was 3000 rep points. – Neil Jul 13 '16 at 15:20