У меня есть родной DLL, что мне нужно установить строковое значение параметра. Ниже приведена подпись метода c ++
__declspec(dllexport) void __stdcall getDetails(_Out_ LPTSTR lpDetails, _In_ UINT uSize)
метод c ++
Я жестко запрограммировал это для return lpDetails = L «test»;
Моя подпись c #
[return: MarshalAs(UnmanagedType.I1)]
[DllImport("test.dll",CharSet=CharSet.Auto)]
static extern bool getDetails(StringBuilder result, System.UInt32 uSize);
код C #
StringBuilder b = new StringBuilder(1000);
getDetails(b, 255);
m = b.ToString(); //always ""Console.WriteLine(m);
Когда я шагаю по коду, я вижу, что значение (lpDetails) установлено на правильное значение. Проблема в c #, я вижу только пустую строку.
Я пробовал вещи, которые я нашел из других постов, но пока не повезло.
Есть несколько вещей не так здесь:
lpDetails=L"test"
сломано. Если вы предоставляете предварительно выделенный буфер для функции (как подразумевает ваша подпись), вам необходимо _tcscpy
детали в lpDetails. Если вы хотите выделить строку внутри функции (как подразумевает ваша реализация, вам нужно объявить lpDetails как LPTSTR*
, но это плохой дизайн, так как вызывающий может не знать, как его освободить (и в этом случае он действительно не может, поскольку «тест» указывает на статическую память в сегменте данных, а не на кучу).Это не будет работать даже без 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
}_
лучшая реализация будет:
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
}_
Других решений пока нет …