user1127081
user1127081

Reputation: 181

Trying to get a string value from native dll

I have a native dll that I need to set a string value of a parameter. Below is the c++ method signature

  __declspec(dllexport) void __stdcall getDetails(_Out_ LPTSTR lpDetails, _In_ UINT uSize)

c++ method

I've hardcoded this for the return lpDetails=L"test";

My c# signature

   [return: MarshalAs(UnmanagedType.I1)]
   [DllImport("test.dll",CharSet=CharSet.Auto)]
   static extern bool getDetails(StringBuilder result, System.UInt32 uSize);

c# code

        StringBuilder b = new StringBuilder(1000);
        getDetails(b, 255);
        m = b.ToString(); //always ""
        Console.WriteLine(m);

When I step through the code I see the value (lpDetails) get set to the correct value. The problem is on the c# all I ever see is an empty string.

I have tried a things I found from other posts but so far no luck.

Upvotes: 0

Views: 555

Answers (1)

Zdeslav Vojkovic
Zdeslav Vojkovic

Reputation: 14591

There are few things wrong here:

  • native method is shown with C signature, not C++ signature (I am nitpicking here :)
  • lPDetails parameter is IN, not OUT, if you want function to write details to a preallocated location (as it seems from the second argument which should denote the length of the allocated buffer)
  • your implementation lpDetails=L"test" is broken. If you provide the preallocated buffer to the function (as your signature implies) you need to _tcscpy the details into lpDetails. If you want to allocate the string inside the function (as your implementation implies, you need to declare lpDetails as LPTSTR*, but this is a bad design as caller might not now how to free it (and in this case indeed it cant as "test" points to a static memory in data segment and not to the heap.

This wouldn't work even without Interop:

LPTSTR pCallerData; // a pointer variable
void getDetails(LPTSTR lpData, /*what do you use second param for? */)
{
  // lpData is a COPY of pCallerData, not a pointer to it, 
  // so you are not modifying pCallerData, but a local variable
  lpData = "test";
  // after the function exits pCallerData still has the same value as before
}_

better implementation would be:

LPTSTR txt[256]; 
getDetails(txt, 256);
// ----
void getDetails(LPTSTR lpData, int size)
{
_tcscpy(lpDetails, _T("Test")); 
// or more realistically _tcsncpy and properly check 
// if details string is longer than size argument
}_

Upvotes: 1

Related Questions