Как мне собрать wstring * в C #?

У меня есть функция в C ++, _GetFileList, которую я пытаюсь получить, чтобы вернуть список / массив строк в код C #. Я не замужем за wstring * или любой другой тип, это то, как пример, который я нашел, сделал это, но я пытаюсь получить его, чтобы он возвращал список / массив, а не просто одну строку. Как я могу упорядочить это, чтобы иметь несколько строк на стороне C #?

Код C ++:

extern "C" __declspec(dllexport) wstring * __cdecl _GetFileList(int &size){
std::list<wstring> myList;
//Code that populates the list correctly
size = myList.size();
wstring * arr = new wstring[size];
for( int i=0;i<size;i++){
arr[i] = myList.front();
myList.pop_front();
}
return arr;
}

Я называю это из C # так:

[DllImport(@"LinuxDirectory.Interface.dll")]
private static extern IntPtr _GetFileList(ref int size);

public bool GetFileList() {
int size = 0;
IntPtr ptr = _GetFileList( ref size );
//WHAT DO I DO HERE TO GET THE LIST OF STRINGS INTO SOMETHING I CAN READ?
}

Я пытался использовать Marshal.PtrToStringUni, Marshal.PtrToStringAnsi, а также структурную, но не смог получить правильный синтаксис.

1

Решение

Вы не P / Invoke может иметь дело только с сигнатурами функций, которые являются C-совместимыми, то есть указатели должны быть на обычные старые данные, а не на полные классы C ++.

Если вы можете переписать код C ++, измените его на вызов SysAllocString и вернуть BSTR, который предоставленный ОС строковый тип предназначен для обмена данными между компонентами, написанными на разных языках. P / invoke уже обладает всей необходимой магией для получения BSTRпросто используйте C # string введите объявление p / invoke.

Если вы не можете изменить сигнатуру C ++, вам придется обернуть ее. Либо используйте C ++ / CLI, который может работать как с классами C ++, так и с .NET, либо используйте стандартный C ++ и создайте и верните BSTR, копируя данные из std::wstring,


Для нескольких строк вы можете использовать предоставляемый ОС тип для массива (SAFEARRAY), который может нести BSTR внутри и снова не зависит от языка. Или может быть проще просто объединить и разделить, используя соответствующий (не появляющийся в данных) символ-разделитель.

Здесь есть действительно полезная информация: https://msdn.microsoft.com/en-us/magazine/mt795188.aspx

Запустив .NET Framework (реализация Microsoft, в Windows), вы можете использовать вспомогательные классы:

#include <windows.h>
#include <atlbase.h>
#include <atlsafe.h>
#include <string>

extern "C" __declspec(dllexport) LPSAFEARRAY GetFileList()
{
std::vector<std::wstring> myList;
//Code that populates the list correctly
size = myList.size();

CComSafeArray<BSTR> sa(size);
int i=0;
for( auto& item : myList ) {
CComBSTR bstr(item.size(), &item[0]);
sa.SetAt(i++, bstr.Detach()); // transfer ownership to array
}
return sa.Detach(); // transfer ownership to caller
}

На стороне C # p / invoke обрабатывает все это:

[DllImport("NativeDll.dll"),
return:MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
public static extern string[] GetFileList();

Ваш вопрос предполагает, что вы можете быть на Linux. К сожалению, в документации, которую я нашел, кажется, говорится, что p / invoke Моно вообще не знает, что делать с массивами переменного размера. Таким образом, вы застряли, делая все вручную, включая освобождение (код в вашем вопросе просачивается new wstring[size] — C # не имеет ни малейшего понятия, как вызвать C ++ delete[] оператор). Посмотри на Mono.Unix.UnixMarshal.PtrToStringArray,

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]