2015-05-25 4 views
0

Я хотел бы интерпретировать вывод следующей неуправляемой функции:Преобразовать IntPtr на символ ** в C#

afc_error_t afc_get_device_info (afc_client_t client, char ***device_information) 

Я импортировать библиотеки DLL с кодом:

[DllImport("libimobiledevice.dll", CallingConvention = CallingConvention.Cdecl)] 
internal static extern short afc_get_device_info(IntPtr client, out IntPtr info); 

Пока Мне только нужно было преобразовать ответ в строку Marshal.PtrToStringAnsi было хорошо. Однако я не знаю, как преобразовать этот IntPtr обратно в char array.

+2

Вы импортируете две различные функции, с разными именами и разным количеством параметров ... И один из них был «char ***» ... (я должен сказать, что «***» - это что-то редкое даже в мире C :-)) – xanatos

+0

@xanatos Да, сэр, я исправил это имя. char *** - это потому, что он возвращает char ** (например, если он возвращает строку, это будет char ** outputString). –

+0

@geislza, а второй пример - пример несвязанного метода той же библиотеки, который вы используете, правильно? – xanatos

ответ

2

Это должно быть что-то вроде:

IntPtr di; 

int result = afc_read_directory(client, @"C:\", out di); 

if (di == IntPtr.Zero) 
{ 
    throw new Exception(); 
} 

IntPtr di2 = di; 

while (true) 
{ 
    IntPtr ptr = Marshal.ReadIntPtr(di2); 

    if (ptr == IntPtr.Zero) 
    { 
     break; 
    } 

    string str = Marshal.PtrToStringAnsi(ptr); 

    if (str == string.Empty) 
    { 
     break; 
    } 

    di2 = di2 + IntPtr.Size; 
} 

Попробуйте, если он работает, то я объясню, как ...

важно вы утечки памяти здесь ...

Я нашел этот пример в C:

char **dirs = NULL; 
afc_read_directory(afc, "/eafaedf", &dirs); 
if (!dirs) 
    afc_read_directory(afc, "/", &dirs); 
printf("Directory time.\n"); 
for (i = 0; dirs[i]; i++) { 
    printf("/%s\n", dirs[i]); 
    free(dirs[i]); 
} 
if (dirs) 
    free(dirs); 

Вы освобождаете память от (см. free внутри цикла, а окончательный -?). В этом случае (и для других методов, возвращающих массивы C-строк, вы можете использовать afc_dictionary_free. Обратите внимание, что другие методы, такие как afc_receive_data, которые возвращают один блок памяти, вы не можете использовать.

+0

Спасибо, что сработало. В одной и той же библиотеке есть функция afc_dictionary_free. Я думаю, что это правильно освобождает. –

+0

@ Geiszla Yep ... Он делает. Просто посмотрел на его исходный код. – xanatos

+0

@Geiszla Если вы хотите использовать этот метод, обратите внимание, что вам нужно изменить код. Я уже обновил ответ. Я модифицировал оригинальный 'IntPtr di', но вам нужно сохранить копию, чтобы использовать ее с' afc_dictionary_free' – xanatos

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