user3462647
user3462647

Reputation: 41

What is the equivalence of LPCTSTR * in C#

I have an unmanaged C++ function residing inside a Dll that I call from my C# application. Here is the signature of the function:

GetCrashMeasurement(LPCTSTR channelName, LPCTSTR properties, LPCTSTR * Values, HANDLE error)

where channelName and properties are input parameter [in]; and Values is an output parameter[out].

I'm also using the Platform invoke from my C# application as follows:

[DllImport("DrvCrashHAL.dll", EntryPoint = "coCRAL_GetCrashMeasurements")]

public static unsafe extern CoStatus GetCrashMeasurements(string sChannel, string sMeasurements, ref string sValues, IntPtr hError);

From my C# application I call the function in the following way:

string Text = "";
intptr herror = intptr.zero;
GetCrashMeasurements("channelname","",ref Text,herror);

But then my program stops exactly at this line without throwing any exception, and all I see in the output window is the following message:

Critical error detected c0000374
Critical error detected c0000374
The program '[4964] ProjectX.exe: Managed' has exited with code 0 (0x0).
The program '[4964] ProjectX.exe: Native' has exited with code 0 (0x0).

My guess is, the problem lies in the marshalling type of LPCTSTR.

Could anyone please tell what I`m doing wrong or point me to the right direction?

Thanks in advance.

Upvotes: 4

Views: 1160

Answers (2)

david.pfx
david.pfx

Reputation: 10853

As far as I can tell from what you've provided, parameters 1, 2 and 4 should marshall just fine. The problem is likely to be parameter 3.

Error c0000374 is heap corruption. That would fit.

The issue in trying to solve your problem is to know what that 3rd parameter does. It's declared as a kind of char**, and as an [out] parameter I would expect it to be output as a char*. In other words, I would expect the function to actually output a pointer, not a string, with the expectation that the caller will receive that pointer and copy a (null-terminated) string from it.

You can investigate calls like this by redefining the entry point as an int* or int** and passing in an intptr. That way you should (a) fix the crash and (b) get to see the output value (as an int or pointer). You may have to do your own marshalling for this one. Given a pointer to a COM BSTR you can easily retrieve the value you need.

However, according to my reading of the Interop spec, this should work correctly with a declaration of out string sValues and not ref. The heap corruption would be happening when the function is called, not when it returns.

This is helpful, if rather technical: http://msdn.microsoft.com/en-us/magazine/cc164193.aspx.

I suggest you try that first. If not, maybe try the debugging route to see what pointer you are getting.

Upvotes: 1

Ulugbek Umirov
Ulugbek Umirov

Reputation: 12807

As @jester noticed LPCTSTR* Values sounds more like an array of strings. Can you try to change your third parameter to be an array of strings?

public static unsafe extern CoStatus GetCrashMeasurements(string sChannel, string sMeasurements, string[] sValues, IntPtr hError);

and call it as follows

GetCrashMeasurements("channelname","",new[] { Text },herror);

Also you can specify MarshalAs on sValues.

public static unsafe extern CoStatus GetCrashMeasurements(string sChannel,
                                                          string sMeasurements,
                                                          [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPTStr)]
                                                          string[] sValues,
                                                          IntPtr hError);

Upvotes: 0

Related Questions