плавать * из C в C # - PullRequest
       10

плавать * из C в C #

7 голосов
/ 08 марта 2011

Я на самом деле не парень из CS, поэтому, если кто-то из вас, гениев, сможет указать мне правильное направление, я буду вечно благодарен.

У меня есть функция командной строки c-кода, котораяиспользуется для записи своих результатов в файл.Я преобразовал его так, чтобы он возвращал данные через массив float * в программу на C ++, например, (чтобы избежать постоянного ввода-вывода файлов):

float * mgrib(int argc, char **argv)

Это сработало отлично.Теперь мне нужно включить это в программу на C #, и здесь дела идут плохо.

Первое, что я сделал, чтобы избежать символа **, - это сделал аргументы последовательностью bool.Это сработало нормально, если я позволю ему все еще записывать в файл.

Проблема заключается в манипулировании массивом с плавающей точкой в ​​стиле C в C #.Внутри c-кода он был выделен с помощью malloc.

Итак, вот все, что я пытался безуспешно (я знаю размер массива):

  1. Make«свободная» функция для экспорта в C # для вызова, чтобы освободить память, когда я закончу с ней.После нескольких циклов C # вылетает без предупреждения.

  2. Освободить malloc из C # с Marshal.FreeCoTaskMem.Тот же результат.

  3. Переместить float * в аргумент и удалить код malloc c.(void mgrib (..., float * data, ...)

__a) Выделите его с помощью Marshal.AllocCoTaskMem.Освободите его с помощью Marshal.FreeCoTaskMem.

__ b) Используйте Marshal.Copy для выделения.Освободите это с Marshal.FreeCoTaskMem (Может быть, это не так?)

Я баловался почти всем, что я мог найти в Интернете.Пожалуйста, дайте мне знать, если нужна дополнительная информация.Я надеюсь, что это просто простая концепция, которую мне не хватает.

1 Ответ

5 голосов
/ 09 марта 2011

Используйте эту подпись для своей функции C (замените mgrib.dll реальным именем библиотеки).

[DllImport( "mgrib.dll", EntryPoint = "mgrib" )]
public static extern IntPtr mgrib(
    int argc,
    [MarshalAs( UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr )]
    StringBuilder[] argv );

Вызовите функцию mgrib следующим образом:

// Prepare arguments in proper manner
int argc = 0;
StringBuilder[] argv = new StringBuilder[ argc ];
IntPtr pointer = mgrib( argc, argv );

Когдавызов завершен, вы можете получить результат следующим образом:

float[] result = new float[ size ];
Marshal.Copy( pointer, result, 0, size );

РЕДАКТИРОВАТЬ :

Поскольку mgrib выделяет память, используя malloc,нам нужно освободить память, используя функцию free.Однако вам придется заключить вызов функции free в другую функцию, которая будет экспортирована из собственной библиотеки.

extern "C" __declspec(dllexport) void mgrib_free( float* pointer );

void mgrib_free( float* pointer )
{
    free( result );
}

, а затем импортировать ее следующим образом:

[DllImport( "mgrib.dll", EntryPoint = "mgrib_free",
            CallingConvention = CallingConvention.Cdecl )]
public static extern void mgrib_free( IntPtr pointer );

И вызвать его следующим образом:

mgrib_free( pointer );
...