2016-10-10 5 views
2

У меня есть эта функция в DLL в C, и я не могу изменить его:Маршал wchar_t ** от C++ до C# как параметр out?

extern "C" SIBIO_MULTILANGUAGE_API_C DWORD getLabel(const char* const i_formName, 
                const char* const i_fieldName, 
                wchar_t** i_output); 

Я знаю, что этот вызов внутри выделяет память для wchar_t* с помощью функции CoTaskMemAlloc.

В C# я обернул эту функцию следующим образом:

[DllImport("sibio_multilanguage_c.dll", EntryPoint = "getLabel", CallingConvention = CallingConvention.Cdecl)] 
private static extern UInt32 _getLabel([In] string i_formName, [In] string i_fieldName, 
             [MarshalAs(UnmanagedType.LPWStr)] out string i_output); 

static public string getLabel(string i_formName, string i_fieldName) 
{ 
    string str = null; 
    UInt32 err = _getLabel(i_formName, i_fieldName, out str); 
    if (0 != err) 
    { 
     throw new System.IO.FileNotFoundException(); 
    } 
    return str; 
} 

Я смог правильно прочитать содержимое wchar_t* но читать таким образом, я не освобождает память, выделенную в функции C ,

Как я могу прочитать wchar_t*, а также уметь его освобождать? Любая помощь очень ценится!

+1

Я считаю, что вам нужно вызвать 'Marshal.FreeCoTaskMem', однако он ожидает' параметр IntPtr' вместо экземпляра 'String'. Вы можете изменить импорт 'getLabel' для использования' IntPtr' и выполнить преобразование строки самостоятельно. – Dai

+0

Вы правы. Я подумал об этом, и я тоже попробовал, но таким образом я не смог правильно прочитать содержание. Вероятно, я сделал что-то не так. Теперь я редактирую вопрос и с этой попыткой. – BugsFree

+0

Вы проверили, предоставляет ли эта библиотека функцию утилиты для очистки памяти объектов, созданных в рамках их других функций? – Anzurio

ответ

0

Благодаря @Dai и @IanAbbot комментарии я пришел к решению, которое прекрасно работает:

[DllImport("sibio_multilanguage_c.dll", EntryPoint = "getLabel", CallingConvention = CallingConvention.Cdecl)] 
private static extern UInt32 _getLabel([In] string i_formName, [In] string i_fieldName, 
             out IntPtr i_output); 

static public string getLabel(string i_formName, string i_fieldName) 
{ 
    IntPtr i_result; 
    string str = null; 
    UInt32 err = _getLabel(i_formName, i_fieldName, out i_result); 
    if (0 != err) 
    { 
     throw new System.IO.FileNotFoundException(); 
    } 
    str = Marshal.PtrToStringAuto(i_result); 
    Marshal.FreeCoTaskMem(i_result); 
    return str; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^